Skip to content

gh gist create#981

Merged
vilmibm merged 25 commits intomasterfrom
gist-create
May 25, 2020
Merged

gh gist create#981
vilmibm merged 25 commits intomasterfrom
gist-create

Conversation

@vilmibm
Copy link
Contributor

@vilmibm vilmibm commented May 20, 2020

Fixes #397

Based on #543; moved over to new PR for CI reasons. Big ups to @wingkwong for getting it started.

This PR adds support for creating gists. You can invoke it in a few ways:

gh gist create hello.py                   # turn file hello.py into a gist
gh gist create --public hello.py          # turn file hello.py into a public gist
gh gist create -d"a file!" hello.py       # turn file hello.py into a gist, with description
gh gist create hello.py world.py cool.txt # make a gist out of several files
gh gist create -                          # read from STDIN to create a gist
cat cool.txt | gh gist create             # read the output of another command and make a gist out of it

It looks like this:

image

Considerations

Currently we don't request the gist scope when creating auth tokens. We didn't want another "stop every user after a release to reauth" since not every user necessarily wants gist support. This PR adds an imperfect helper, ensureScopes that lets us prompt for re-auth in a given command.

In the future the best solution would be the ability to retry failed requests when we determine they failed for valid scope reasons, but that was too much effort for now.

I'd like to add some more tests but otherwise it's ready for review.

@tierninho
Copy link
Contributor

I take it the -R flag does not work here as you must be in the directory from which you run to command?

I created the hellp.py file in my repo and used the flag bin/gh gist create hello.py -R tierninho/Blah, but got:

failed to collect files for posting: failed to read file hello.py: open hello.py: no such file or directory

@vilmibm
Copy link
Contributor Author

vilmibm commented May 21, 2020

the -R flag is not relevant. its presence in docs for commands like this is a bug as far as i remember?

either way: the arguments are file paths and relative only to the directory you're in when you run the command and not to any repositories.

Copy link

@ampinsk ampinsk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks awesome from my perspective! I'm curious if there would be any value to a default behavior when there are no arguments (maybe make a gist out of whatever is in the directory? though I can see that being unexpected/destructive), but I'm totally comfortable thinking about that as a follow up!

Copy link
Contributor

@mislav mislav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job getting this over the finish line! 🎉

}

var gistCreateCmd = &cobra.Command{
Use: `create {<filename>|-}...`,
Copy link
Contributor

@mislav mislav May 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: since - technically can't be repeated, a more precise usage expression would be:

create {<filename>... | -}

but I would be fine with simply omitting the information about - from the usage line and make a note of it in the docs where we talk about stdin.

RootCmd.AddCommand(gistCmd)
gistCmd.AddCommand(gistCreateCmd)
gistCreateCmd.Flags().StringP("desc", "d", "", "A description for this gist")
gistCreateCmd.Flags().BoolP("public", "p", false, "When true, the gist will be public and available for anyone to see (default: private)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: to simplify the language of this flag description, might we use the same language as in gh repo create?

--public               Make the new repository public (default: private)

The key would be to eliminate the When true prefix since "when true" is basically implied for all boolean flags.

var gistCreateCmd = &cobra.Command{
Use: `create {<filename>|-}...`,
Short: "Create a new gist",
Long: `gh gist create: create gists
Copy link
Contributor

@mislav mislav May 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the first sentence of Long description, we usually have a simple description of what the command does, e.g.

$ gh help pr list
List and filter pull requests in this repository
...

This can be just "Create a GitHub gist", I feel. We don't need to hardcode gh gist create since that part the user already entered in their prompt.


Gists can be created from one or many files. This command can also read from STDIN. By default, gists are private; use --public to change this.

Examples
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found this out by accident the other day: Cobra has a dedicated Example field! spf13/cobra@bf480fe

Comment on lines +64 to +65
// In the future we'd rather have the ability to detect a "reauth needed" scenario and replay
// failed requests but some short spikes indicated that that would be a fair bit of work.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

props to explaining all this 👏

if err != nil {
return fmt.Errorf("failed to check STDIN: %w", err)
}
if (info.Mode() & os.ModeCharDevice) != os.ModeCharDevice {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL this way of inspecting stdin 🌟 Does this work on Windows?

In my experience, the easiest way to discern whether something was piped to a command (vs a command being called on its own) is to check whether stdin is not connected to a terminal.

return fmt.Errorf("did not understand arguments: %w", err)
}

info, err := os.Stdin.Stat()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we always stat stdin unconditionally, or just when the file list is empty?

var err error
if f == "-" {
filename = fmt.Sprintf("gistfile%d.txt", i)
content, err = ioutil.ReadAll(stdin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: it's not strictly necessary, but I think that closing stdin after having exhausted it would be the right thing to do, especially because it would lead to a clearer error message if someone tried to pass - multiple times.

@vilmibm vilmibm merged commit 9ebeb5f into master May 25, 2020
@wingkwong
Copy link
Contributor

@mislav @vilmibm Now we got gist create. May I know if gist list/edit/delete are in cli roadmap? If so, I may work on them.

@dardo82
Copy link

dardo82 commented Jun 23, 2020

@wingwong I'd like to be able to edit gists from the cli too,can you please implement the feature?

@wingwong
Copy link

wingwong commented Jun 23, 2020 via email

@wingkwong
Copy link
Contributor

@dardo82 Sure. I'll implement it when I'm free.
@wingwong It happens sometimes. Sorry about it.

@mislav mislav deleted the gist-create branch June 23, 2020 13:51
@dardo82
Copy link

dardo82 commented Jun 23, 2020

@wingkwong thanks,how can I help you? 🤓

@mislav
Copy link
Contributor

mislav commented Jun 23, 2020

Hi, for discussing new feature ideas, such as the ability to list or edit gists, please first open a new issue for it so we can have a discussion there. I feel that this PR should only be a place for discussing the pr create functionality that got merged. Thank you!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: add command to create gist

7 participants