-
Notifications
You must be signed in to change notification settings - Fork 6.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support getting both JSON and template output #8415
Comments
@rwalkerands : thank you for opening up this issue! 🤗 How would you expect to separate out multiple output streams if I don't really see a clean way to achieve what you're hoping for unfortunately. That said, I can talk about how I typically work with JSON for scripting without duplicate Like REPOS=$(echo "${PARSE_DATA}" | jq -r '.data.organization.repositories.nodes')
for REPO_DATA in $(echo -n "${REPOS}" | jq -r '.[] | @base64'); do
_jq() {
echo -n "${REPO_DATA}" | base64 --decode | jq -r "${1}"
}
OWNER=$(_jq '.owner.login' | tr '[:upper:]' '[:lower:]')
REPO_NAME=$(_jq '.name' | tr '[:upper:]' '[:lower:]') This way, you can pull and even paginate data while limiting the number of calls you're trying to make. |
I followed this issue because I had the same feature request, and am surprised this is considered too difficult to implement. The template feature is just wrapping templating functionality in Go to my understanding, and the feature request is that the input to this template can be filtered using jq. At least, in my case that was all I wanted, and was surprised to find it incompatible (so I had to pipe to jq manually, despite this being bundled in I don't need to handle "multiple output streams" and I don't want to rely on writing to disk, this seems pretty simple: just pipe the output of the |
I wouldn't, which is why I offered two proposed solutions which are different from that. To repeat them:
To expand on (2): add a new top-level command, say I happen to like the implementation of templates provided by gh. Here's part of my script that produces a report on open PRs for a repo:
Yes, I probably could implement this template using Bash/jq. But I'd rather not have to. |
@rwalkerands : Thanks for clarifying your thoughts further as initially it seemed you might be asking for something that was impossible: having JSON and template output both streaming through standard out. Seeing that you and @lmmx were considering multi-phase processing via JSON + JQ then template processing, I believe this issue has come up previously as I recall asking a similar question. At the time, the feedback I received was:
Personally, I'm open to the idea still though the
This is certainly outside of the scope of what the GitHub CLI team and maintainers can support. It is something I myself have looked into for similar reasons however I didn't truly find anything that allowed users to arbitrary define Go templates and pass in JSON via file or standard input.
Currently, this wouldn't work or work well given commands that require a |
Why not just have E.g., gh api ... | tee output.json | jq ... Having a CLI do "everything" seems not only a maintenance issue, but also limiting: it's not always going to work the way people want, and as a consequence devs keep having to add knobs which increases maintenance costs for complexity. Keeping it flexible might be better. If you want something easy to use in scripts, consider at least keeping it in the ecosystem as an extension. You could easily have an extension both tee and format JSON using Go templates and install that if needed with the #!/usr/bin/env bash
# this will install or uprade the extension, or no-op if already installed
gh ext install --force heaths/gh-merge-json
# using `gh ext exec` is good for scripts and helps avoid future possible ambiguity, which happened to me a while back
gh api ... | gh ext exec merge-json Just my $0.02. |
I added support to Example usage: gh ext install --force heaths/gh-merge-json > /dev/null # or just $null in pwsh
gh api graphql --paginate -f query='
query($endCursor: String) {
viewer {
repositories(first: 100, after: $endCursor) {
nodes { nameWithOwner }
pageInfo {
hasNextPage
endCursor
}
}
}
}
' | gh merge-json --template '{{range .data.viewer.repositories.nodes}}{{tablerow .nameWithOwner}}{{end}}' --tee repos.json |
Because using jq to implement the sort of template(s) I want to have (see #8415 (comment)) appears to be quite cumbersome ... if it is even possible. (E.g., how to do
You answered your own question. I already looked, but didn't find. Very happy to be pointed at a small standalone-app that does JSON through a Go-like template to text. Indeed, thank you for the pointer to https://github.com/heaths/gh-merge-json ; I have now tried it and confirmed that it works for me. |
Thanks for sharing your insights, @heaths ❤️ There is definitely a fine line of how GitHub CLI aligns with other tools in the Unix design principle we're trying to exercise being an extremely small team. All of that to say, @rwalkerands , I hope you have some options for short/medium term workarounds as discussed above while I bring this up for discussion with the other maintainers on ramifications of refactoring the code involved: Lines 185 to 220 in 57f6787
|
Indeed, I am now using |
[shameless plug] @rwalkerands if you like it, consider starring heaths/gh-merge-json to to help discovery on https://github.com/topics/gh-extension 😉 If not, that's cool too. Won't change support or feature ideas unlike some repos in the news recently. Just helps others find it easier in case it might help them. On that note: @andyfeller it'd be cool if GitHub defaulted a search from a topic to include that topic when you hit |
Done (and was happy to do so). |
Kind of like jumping to search within a repo will add |
I recently raised this, which was closed as a dupe of this issue: I'd like to add my support for having whatever data manipulations I provide in It might be fiddly, but that's something I as a user should be allowed to choose to opt into IMO. There shouldn't be any backwards compatibility issues as Personally I find the fact that I can't use both together a worse user experience. I have no strong opinions on whether tl;dr: Supporting
@rwalkerands Since I hacked something together for this recently, this was how I solved it:
I also raised this, which might be helpful if possible/implemented |
Most commands use gh issue list --json number,title --jq 'sort_by(.title)' --template '{{range .}}{{.title}}{{end}} However, in this example since
|
@andyfeller after an initial attempt to do this entirely in With that in mind, and because I think |
@heaths @0xdevalias we see the value of this, and it doesn't seem particularly tricky to implement based on the proposed PRs. That said, we are a bit swamped at the moment with other work so it may take a little time to ensure we are confident in the UX and documentation that needs to go with it. @heaths do you see value for extension authors putting this in |
Both. It definitely keeps the code in the CLI cleaner, but also allows extension authors to easily filter JSON output before applying templates (baked in or otherwise). E.g., say you wanted to output the top 10 issues by vote in a nice, neat table. If your GraphQL statement had something like: reactions(content: THUMBS_UP) {
totalCount
} You can easily morph and filter: t := template.New(ios.Out, ios.Width(), ios.ColorEnabled());
t.Parse("{{range .}}{{tablerow .number .title .votes}}{{end}}")
template.ExecuteFiltered(r,
"map({number, title, votes: .reactions.totalCount}) | sort_by(.votes) | reverse | .[:2]") Much easier than all the Go code to do the same. |
Describe the feature or problem you’d like to solve
I'd like commands such as
gh pr list
to be able to give me both JSON output and to be able to apply a template.The comment at #3012 (comment) notes as an aside:
I'm using
gh pr list
in a (Bash) script that both generates pretty output for the user, and also does some other processing of the PRs.I'd like to avoid having to run
gh pr list
twice.What doesn't really work for me: add
{{ . }}
in the template. This gives me output in Go syntax, which I can't otherwise use.Proposed solution
I have no particular preference for a solution. Obvious thought: add an option to output the JSON to a file.
Or, a completely different approach: add a new command that takes JSON input (from stdin and/or a file) and applies a template.
The text was updated successfully, but these errors were encountered: