Skip to content
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

Fallback clone from user organization #9044

Open
wants to merge 3 commits into
base: trunk
Choose a base branch
from

Conversation

maaslalani
Copy link

Fixes #2000

This PR solves a problem I generally encounter when cloning repositories. This
is a pretty specific and personal annoyance so feel free to close if it doesn't
fit into the philosophy.

When cloning repositories, I sometimes forget to add the owner:

$ gh repo clone lipgloss

Then, I receive an error:

GraphQL: Could not resolve to a Repository with the name 'maaslalani/lipgloss'. (repository)

Then, I specify the owner and everything is fine:

$ gh repo clone charmbracelet/lipgloss
# Cloning into 'lipgloss...'

It would be quite nice if gh could clone the repo for me if it knows which
organizations I generally clone from (the ones I belong to). This PR performs a
fallback to cloning the repository if the user doesn't specify the owner.

So, if a user runs:

$ gh repo clone lipgloss

The clone will first try maaslalani/lipgloss, find that it is not there,
then either tries NixOS/lipgloss or charmbracelet/lipgloss and clones
charmbracelet/lipgloss since it exists.

NB: If the user runs:

$ gh repo clone maaslalani/lipgloss
# GraphQL: Could not resolve to a Repository with the name 'maaslalani/lipgloss'. (repository)

They will receive the same error since they explicitly mentioned the
organization they wanted the repository from.


Some improvements to add (if we want to continue with this approach):

  1. Inform the user which repository we're cloning from if it's a fallback.
  2. Add tests:
    2.1. gh repo clone dotfiles, repo does exist in user.
    2.2. gh repo clone lipgloss, repo does exist in fallback org.
    2.3. gh repo clone obviously-doesnt-exist-anywhere, repo does not exist anywhere.
    2.4. gh repo clone maaslalani/lipgloss, repo does not exist in explicit owner, but does exist in org.
    2.5. gh repo clone charmbracelet/lipgloss, repo exists in org.
    2.6. gh repo clone .github, repo exists in multiple orgs.
  3. Make org limit configurable, current set to 5.

@maaslalani maaslalani requested a review from a team as a code owner May 3, 2024 20:35
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label May 3, 2024
@cliAutomation cliAutomation added this to Needs review 🤔 in The GitHub CLI May 3, 2024
@andyfeller
Copy link
Contributor

This PR solves a problem I generally encounter when cloning repositories. This
is a pretty specific and personal annoyance so feel free to close if it doesn't
fit into the philosophy.

I can tell you I have clones from multiple organizations and this has bitten me numerous times, too. ❤️

Copy link
Contributor

@andyfeller andyfeller left a comment

Choose a reason for hiding this comment

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

I've long wished we had a way to capture an owner for a given directory for those of us who organize based on organization:

cat ~/.config/gh/config.yml
aliases: {}
version: "1"
directoryOwners:
  path/to/owner: owner
  path/to/owner2: owner2

pkg/cmd/repo/clone/clone.go Outdated Show resolved Hide resolved
return err
}

org, err := promptForOrg(apiClient, repo)
Copy link
Member

Choose a reason for hiding this comment

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

If we do proceed with something like this we need to ensure this only happens if opts.IO.CanPrompt() is true. This supports people who aren't using TTY and anyone who has GH_PROMPT_DISABLED set.

Copy link
Author

@maaslalani maaslalani May 6, 2024

Choose a reason for hiding this comment

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

Ah, nice, that makes sense. Thanks for letting me know. If we do proceed with this do we want to show an accessible menu that huh provides (in the event of people using screen readers)? Perhaps introduce GH_PROMPT_ACCESSIBLE? This could also come later as well.

image

@williammartin
Copy link
Member

williammartin commented May 6, 2024

Initially playing around with this I'm not sure about the current approach. The primary concern is that listing the orgs can easily be more confusing or annoying than not. Here's what I experienced:

image

There are two problems here:

  • None of these orgs actually contain cli
  • The org that does contain cli isn't included

I don't think expanding the list of orgs by itself resolves this. It would be nice if we could search within the orgs that the user is a part of and only show those but unless GitHub search supports this (have asked to see if anyone has any ideas) that would involve a lot of network requests as you saw in 9bf322b.

@williammartin
Copy link
Member

williammartin commented May 6, 2024

Maybe there are some heuristics we could apply like:

  • If the org list only contains n orgs, query them to see whether they contain a repo of the correct name, and only show those
  • If the org list contains more than n orgs, show the whole list

Would that solve for the most common case, while keeping the request count down?

@williammartin
Copy link
Member

williammartin commented May 6, 2024

@maaslalani how often do you want to clone from charmbracelet and maaslalani without providing the owner/? In #2000 the team said they would accept default_owner but that's a bit different than fallback which is the word you used.

@maaslalani
Copy link
Author

Maybe there are some heuristics we could apply like:

  • If the org list only contains n orgs, query them to see whether they contain a repo of the correct name, and only show those
  • If the org list contains more than n orgs, show the whole list

Would that solve for the most common case, while keeping the request count down?

Yeah I quite like this approach. I would also add one more case, if the org list only contains n repos and we query them and only one of the queried orgs has the repo, simply clone that one without showing any prompt (If we really want to confirm then would perhaps show a Confirm (yes / no) prompt instead).


I don't think expanding the list of orgs by itself resolves this. It would be nice if we could search within the orgs that the user is a part of and only show those but unless GitHub search supports this (have asked to see if anyone has any ideas) that would involve a lot of network requests as you saw in 9bf322b.

Yeah, you're absolutely correct. I like the idea of having a query that can find repositories matching the name of the repo the user tried to clone with different owners so that all the listed options are valid clone-able repositories. So perhaps, we can list repositories from GitHub matching the name and filter by owners that the user has access to. Is there a query for this?


@maaslalani how often do you want to clone from charmbracelet and maaslalani without providing the owner/? In #2000 the team said they would accept default_owner but that's a bit different than fallback which is the word you used.

I almost never specify the owner/ the first time, only when I get an error. This might be sort of an edge case because charmbracelet is a long name. I almost always want to clone from either maaslalani/ or charmbracelet/ so for me I think being able to specify fallback_owner would be better than default_owner since if charmbracelet was the default_owner I would have the same problem but with my cloning my own repos rather than the organizations.

@andyfeller
Copy link
Contributor

andyfeller commented May 6, 2024

Would that solve for the most common case, while keeping the request count down?

What is the most common use case?

  1. users with repositories in username space?
  2. users only in 1 GitHub organization?
  3. users in 2+ GitHub organizations?
  4. users who clone OSS repositories?

My experience is that people fall into multiple buckets, very rarely just 1.

Allowing users to change the default owner might be the best now solution

Again, I think the robust solution is enabling users to define the user for a given directory, however that is more work. If we don't want to implement it just yet, it would be easier to iterate on allowing users to change the default owner rather than getting clever on how to find the owner they didn't specify.

@williammartin
Copy link
Member

So perhaps, we can list repositories from GitHub matching the name and filter by owners that the user has access to. Is there a query for this?

I'm not sure it's really feasible. For example searching cli gives more than 1 million results.

My experience is that people fall into multiple buckets, very rarely just 1.

I'm not sure where you're going with this @andyfeller sorry. When I say "common case" I mean, the most common case of someone calling gh repo clone <repo_without_org> which I would say is "There are a small number of owners that contain repos I work in, and I have one of those in mind for this repo I'm cloning". That definition would exclude "I am a part of many organizations" and "I have a repo in mind that belongs to some organization that I am not a part of e.g. OSS" which feel like uncommon cases.

Again, I think the robust solution is enabling users to define the user for a given directory

There's some discussion about filesystem organisation in the multi-account world as well so let's not rule it out. Perhaps you could sketch out what the UX for this would be? I get the sense that it will cause friction trying to nudge our users into managing their directory structure in a certain way.

@andyfeller
Copy link
Contributor

My experience is that people fall into multiple buckets, very rarely just 1.

I'm not sure where you're going with this @andyfeller sorry. When I say "common case" I mean, the most common case of someone calling gh repo clone <repo_without_org> which I would say is "There are a small number of owners that contain repos I work in, and I have one of those in mind for this repo I'm cloning". That definition would exclude "I am a part of many organizations" and "I have a repo in mind that belongs to some organization that I am not a part of e.g. OSS" which feel like uncommon cases.

Mostly that many enterprise users work in situations where there are hundreds or thousands of organizations within their enterprise. Perhaps we can talk to someone inside GitHub for greater insights on user demographics 🤔

Regardless, I think we're on the same page about "common case" 👍

@andyfeller
Copy link
Contributor

Again, I think the robust solution is enabling users to define the user for a given directory

There's some discussion about filesystem organisation in the multi-account world as well so let's not rule it out. Perhaps you could sketch out what the UX for this would be? I get the sense that it will cause friction trying to nudge our users into managing their directory structure in a certain way.

$ gh set-directory-owner --help
Configures the current directory to use a predetermined GitHub user or organization similar to `GH_HOST` when a repository context is unavailable.

USAGE
  gh set-directory-owner <org> [flags]
  gh set-directory-owner <user> [flags]

ALIASES
  gh set-dir-owner

FLAGS
      --dir string   Path to directory (default ".")

INHERITED FLAGS
  -h, --help

$ cat ~/.config/gh/config.yml
aliases: {}
version: "1"
directoryOwners:
  /Users/andyfeller/repos/andyfeller_volcano: andyfeller_volcano
  /Users/andyfeller/repos/andyfeller-volcano: andyfeller-volcano
  /Users/andyfeller/repos/cli: cli
  /Users/andyfeller/repos/github: github
  /Users/andyfeller/repos/tinyfists: tinyfists

$ pwd
/Users/andyfeller

$ cd repos/cli
$ gh repos list

Showing 12 of 12 repositories in @cli

NAME                         DESCRIPTION                                                                             INFO               UPDATED             
cli/cli                      GitHub’s official command line tool                                                     public             about 32 minutes ago
cli/go-gh                    A Go module for interacting with gh and the GitHub API from the command line.           public             about 3 days ago
cli/gh-extension-precompile  Action for publishing binary GitHub CLI extensions                                      public             about 8 days ago
cli/gh-webhook                                                                                                       public             about 1 month ago
cli/cli-ghsa-7f52-83gx-mvr8                                                                                          private            about 2 months ago
cli/cli-ghsa-2ww6-x9gc-cj97                                                                                          private            about 3 months ago
cli/safeexec                 A safer version of exec.LookPath on Windows                                             public             about 3 months ago
cli/browser                  Go helpers to open URLs, files, or readers in a web browser.                            public, fork       about 6 months ago
cli/shurcooL-graphql         Package graphql provides a GraphQL client implementation.                               public, fork       about 7 months ago
cli/oauth                    A library for performing OAuth Device flow and Web application flow in Go client apps.  public             about 8 months ago
cli/scoop-gh                 [DEPRECATED] scoop packaging for the github cli                                         public, archived   about 1 year ago

$ cd ../tinyfists
$ gh repo list

Showing 28 of 28 repositories in @tinyfists

...

$ cd ~/
$ gh repo list

Showing 30 of 81 repositories in @andyfeller

...

In writing this out, I imagine this probably needs to be its own command set as we need more than set; it could live in gh config as a nested set 🤷

But the basic premise being that we can check if the current directory has a mapping when we are trying to resolve the owner if GH_HOST is not set. The idea being if you traverse into a repo from this directory, the mapping is unnecessary because the repository context is available, so it is only ever checking the current directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external pull request originating outside of the CLI core team
Projects
No open projects
The GitHub CLI
  
Needs review 🤔
Development

Successfully merging this pull request may close these issues.

Support different default OWNER in gh repo clone REPO
4 participants