cli icon indicating copy to clipboard operation
cli copied to clipboard

`gh config base` a way to configure the base repo

Open bchadwic opened this issue 2 years ago • 19 comments

I got tired of modifying my git config -e to switch my base repo, so I made a command for personal use.

After looking to see if others had similar problems, I found a lot of issues revolving the base repo and its obscurities.

I'm opening this to hopefully help all the future and current users who:

  1. might be new and don't understand what the base repo does (the help section explains the base repo) #4688 #2090
  2. might accidentally pick the wrong base repo initially (like I did 🤦‍♂️) #2300
  3. might want a short hand to quickly swap what remote gh points to for commands (especially combined with aliases) #1481 Sorta related #1837 https://github.com/cli/cli/issues/2657#issuecomment-768667054 Good start to this functionality

I think with the amount of requests and the void in documentation about the base repo, something like this should be included in the tool.

It needs work and tests, but this is what it looks like in action:

$ gh config base --help
The base repository is used to determine which repository gh
should automatically query for the commands:
        issue, pr, browse, run, repo rename, secret, workflow


USAGE
  gh config base <git remote name> [flags]

FLAGS
  -v, --view   View the current configured default repository

...

$ gh config base -v
base repo has not been specified yet

$ gh config base
? Which should be the base repository (used for e.g. querying issues) for this directory? cli/cli

$ gh config base -v
upstream

$ gh config base origin

$ gh config base -v
origin

$ gh config base foo
could not find local remote name foo

bchadwic avatar Dec 06 '21 09:12 bchadwic

@bchadwic The team discussed this feature offline and we all agreed that it is a great idea. We came up with a proposed UX design for this as well. Let us know what you think.

// No argument interactive
gh repo default 
// This would display current default repo and prompt user if they would like to change it

// No argument non-interactive 
gh repo default
// This would just display current default repo

// Argument provided for both interactive and non-interactive
gh repo default some-repo
// This would set the default repo to some-repo
// If there is no matching git remote for some-repo then return error

// Run from outside of a git repo
gh repo default
// This would return an error

While the code refers to this feature as "base" repo we want to use "default" when displaying to the user as it has more meaning.

Additionally we thought it would be nice to have a --reset-default-repo flag for all commands that utilize the default repo functionality, i.e. any command that uses the SmartBaseRepoFunc. This flag would reset the default repo and then prompt the user to select a new default. This functionality is a bit more complex to add. To start I would suggest just working on adding the gh repo default command and we can go from there. How does that sound?

samcoe avatar Jan 13 '22 09:01 samcoe

@samcoe Sounds great, I agree that gh repo default is much more sensible than gh config base.

Since dailying the command, I find I use gh config base -v (aliased as gh b -v) much like git branch. It's exclusively a quick way for me to see what I'm pointing to. Having gh repo default display then always prompt might become an annoyance for interactive users. Especially those who switch around a lot that just need a quick reminder where they're pointing (i.e. instead of always typing n + Enter).

After some thought, I'm ok with leaving out an exclusive view option if my concerns don't seem to be an issue. I only want to voice my experience with using this command before it gets officially implemented 👍

Let me know if that's the final design the team would like to go with, I'd be happy to do some work on this.

Also I like the idea of --reset-default-repo!

bchadwic avatar Jan 14 '22 04:01 bchadwic

Also a view option could serve as a list of available remotes

Merely a suggestion...

// No argument interactive
gh repo default 
// This would prompt the user to select a remote

// No argument non-interactive 
gh repo default
remote name is required when not running interactively, use `--view` to see available remotes

// No argument interactive and non-interactive --view (similar to git branch except * = default)
gh repo default --view
  origin
* upstream

vvvvvvvvvvvvvvvvv
same as team's design

bchadwic avatar Jan 14 '22 04:01 bchadwic

@bchadwic I like the idea of a dedicated flag that will skip the prompt and just display the current default since I can imagine many users just forgetting their default and wanting to see what it is. I am not sure --view is the right name for that flag but we can discuss that more once the implementation is done since it is just a name change.

samcoe avatar Jan 18 '22 07:01 samcoe

I have a suggestion for keeping this simpler. Literally the only design goals for this command right now are that it:

  1. Allows you to reset your previously chosen default;
  2. (nice-to-have) Shows the current result of the base repo resolution.

I would avoid adding much more functionality to this command; especially the kind that does different things in interactive and non-interactive modes. Primarily, I would avoid adding any kind of prompting behavior to the command, which would also alleviate the need for adding flags to disable the prompting behavior.

Here's how I imagine the command would work:

$ gh repo default
#=> "cli/cli"

$ gh repo default --reset

$ gh issue list
# (prompts you to select the new default)

@samcoe What do you think?

mislav avatar Jan 19 '22 18:01 mislav

Would you still be able to pass in a remote name to set the default?

$ gh repo default origin

bchadwic avatar Jan 19 '22 18:01 bchadwic

@mislav I can understand the desire to keep this simple, the reason I thought that this command should allow setting the default repo was to remove the responsibility of setting a default from other commands. In the example you listed the issue list command has a prompt for setting a new default, if we allow this command to set a default then issue list can simply error out and instruct the user to run gh repo default.

Having this one command be able to reset/set/list/etc is a lot of functionality which is why I proposed, offline in slack, introducing a new top level object of a remote, then we could have a set of commands to provide this functionality instead of just one nested under the repo object.

Overall, I don't have strong opinions here but I do anticipate users asking for the feature of being able to set the default through this command.

samcoe avatar Jan 20 '22 07:01 samcoe

Would you still be able to pass in a remote name to set the default?

@bchadwic I personally can't see how that interface would add any value over the existing prompt that asks you to select the base repo.

Here's what currently happens if I clone bchadwic/cli and run gh issue list:

/tmp/bchadwic-cli [trunk] $ gh issue list
? Which should be the base repository (used for e.g. querying issues) for this directory?
> cli/cli
  bchadwic/cli

Note that there was only a single git remote "origin" pointing to bchadwic/cli, but the interactive prompt also includes its parent repository as an option, even if it isn't present as a git remote. How would I make the same choice using gh repo default <remote>?

Furthermore, it should be much more clear to the user when choosing from a prompt that lists repositories as owner/repo rather than having an interface that lets you choose between git remote names. Seeing gh repo default origin by itself contains little information unless you know exactly where "origin" points to.

mislav avatar Jan 20 '22 17:01 mislav

In the example you listed the issue list command has a prompt for setting a new default, if we allow this command to set a default then issue list can simply error out and instruct the user to run gh repo default.

@samcoe Aah, gotcha! If the goal is that other commands will error out when there is ambiguity, then I agree that we should add more functionality to the new dedicated command. Then instead of --reset, I propose something like:

gh repo default --select
? Which should be the base repository (used for e.g. querying issues) for this directory?
> cli/cli
  bchadwic/cli

which is why I proposed, offline in slack, introducing a new top level object of a remote, then we could have a set of commands to provide this functionality instead of just one nested under the repo object.

That's a worthwhile consideration! I agree it would make slightly more sense if these commands were nested under remote rather than repo, since they're mostly about choosing a remote.

mislav avatar Jan 20 '22 17:01 mislav

Ah I didn't do my due diligence; I thought that gh looked at the git config to resolve the base repo, my apologies @mislav

Given that this will be referred to by various commands, I think it now makes more sense for the new command to prompt the default without a flag. I say this to keep things intuitive for new users and to keep directions uniform given that this command will be similar to auth now.

For example, when you run gh pr create without an authentication you get a very intuitive:

To authenticate, please run 'gh auth login'.

Likewise when you run gh pr create without a repo specified you should get something uniform to auth like:

To select a default repo, please run 'gh repo default'.

Simple, and similar to what already exists:

// always prompts a new default
$ gh repo default
? Which should be the base repository (used for e.g. querying issues) for this directory?
> cli/cli
  bchadwic/cli

$ gh repo default --view
#=> "cli/cli"
or
#=> a repo has not been specified yet, run 'gh repo default' to select a default

I'm not attached to --view this was just a suggestion based off other command flags.

Also I'm unsure of what the message would be for non-interactive users.

bchadwic avatar Jan 25 '22 06:01 bchadwic

@bchadwic I agree with the approach of interactive by default, it is the norm with other commands.

samcoe avatar Jan 26 '22 06:01 samcoe

If the team likes the latest design mentioned then I can start revising my pr.

@samcoe if --view seems unintuitive, would --current be more appropriate diction to check the current default repo?

$ gh repo default --current
#=> "cli/cli"

bchadwic avatar Feb 02 '22 04:02 bchadwic

@bchadwic The team is onboard with the direction you proposed. The main concerns we want to make sure are covered:

  • With the interactive by default option we must also provide a way to use the command non-interactively
  • In interactive mode if there is a default already chosen we want to indicate to the user which listed option it is, perhaps using Surveys default option mechanism
  • Lastly, if --view flag is used and a default is not set yet it should output to the user to run the command without the --view flag. We can start with --view flag name and reevaluate it at the end.

Let me know if you have any further questions about the direction!

samcoe avatar Feb 02 '22 12:02 samcoe

@samcoe

Hey sorry for the delay, I'm picking this back up.

#1706

In non-interactive mode, the prompt is skipped and we default to the first git remote instead.

Does this still apply? Or is the remote strategy changing for non-interactive users with this new command?

bchadwic avatar Mar 02 '22 05:03 bchadwic

@bchadwic Lets leave that behavior in place for now and address it in a follow up PR. In the future, in the scenario that there are two or more remotes and no default is selected we will want to error out and instruct the user to use this new command to set the default.

samcoe avatar Mar 02 '22 08:03 samcoe

@samcoe , I finished what seems to be the functionality the team is after. I'm not sure if it's ready for a final review but if you have the time, a look over would be greatly appreciated 😃

A couple things to note:

  1. I haven't tested any of the additional functions in context.go because I'm not sure if extracting functions from context.BaseRepo() was the best solution. (Are there plans to make BaseRepo an interface? Like what Mislav is working on with git clients https://github.com/cli/cli/pull/4900)
  2. I also wasn't sure what to put in the help section other than what I might find helpful

Thank you!

bchadwic avatar Apr 06 '22 05:04 bchadwic

@bchadwic We appreciate your hard work on this and patients on the follow through. In an effort to keep this from lingering on our side too long and wanting to see this shipped in the next release I went ahead and pushed a commit that does a couple things:

  1. Moves code you added to the context package into the default package so that it would be more self contained. The context package is a bit of a relic of the past and we refrain from adding to it whenever possible. Ideally, one day it will go away completely and its functionality will be replaced by a more appropriately named robust package.
  2. Adds tests for the default command. Although they are failing because I am using strings.Cut which was introduced in Go 1.18, I will fix that shortly.
  3. Added some polish and handling of edge cases that were not covered before. There is probably more to be done with the UX and documentation here so that usage of this command is clear.

samcoe avatar Apr 20 '22 07:04 samcoe

Thank you @samcoe ! I think the hold up has been on my side so I appreciate you doing the heavy lifting. I'll look through the code later to see how I could improve for next time 👍

bchadwic avatar Apr 20 '22 12:04 bchadwic

my TODO:

  • merge trunk
  • better name?
  • evaluate UX

vilmibm avatar Aug 22 '22 16:08 vilmibm