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

Allow default host to be determined based on configuration preference #160

Open
andyfeller opened this issue May 15, 2024 · 8 comments
Open

Comments

@andyfeller
Copy link
Contributor

Problem I'm dealing with

Terminal users who are not terminal savvy finding the environment variable only approach to overriding the default host logic confusing.

For multi-account users whose primary GitHub host is not github.com, they must use GH_HOST environment variable to target the appropriate host for core GitHub CLI commands or GitHub CLI extensions without repository context. It is also possible for core GitHub CLI commands and GitHub CLI extension authors to add support for --hostname flag to explicitly communicate this can be set / overridden but must be added intentionally.

The problem comes in for terminal users who are not savvy to working with terminals:

  1. This setting must be managed separately from hosts authenticated via gh auth login
    if the user gh auth logout from this host, then errors occur

  2. Shells offer different levels of scoping environment variables

    • Command-specific (GH_HOST=... gh api ...)
      PowerShell does not support this
    • Session-specific (export GH_HOST=...)
    • Semi-permanent (.zshrc, .bashrc, ~/.config/powershell/profile.ps1)
  3. Inconsistent experiences for users unfamiliar with login sessions versus non-interactive sessions
    .zprofile vs .zshrc, .bashrc vs .bash_profile

Ideas to address this

What if we could indicate which host should be the default?

$ cat ~/.config/gh/hosts.yml 
github.ghe.com:
    default: true
    git_protocol: https
    users:
        andyfeller:
    user: andyfeller
github.com:
    git_protocol: https
    users:
        andyfeller:
    user: andyfeller

In the example above, I want to specify that github.ghe.com is my default host in the event that the host can't be determined by repository context.

This would involve change to the following logic for determining default host:

go-gh/pkg/auth/auth.go

Lines 130 to 150 in dbd982e

// DefaultHost retrieves an authenticated host and the source of host.
// The source can be either an environment variable or from the
// configuration file.
// Returns "github.com", "default" if no viable host is found.
func DefaultHost() (string, string) {
cfg, _ := config.Read(nil)
return defaultHost(cfg)
}
func defaultHost(cfg *config.Config) (string, string) {
if host := os.Getenv(ghHost); host != "" {
return host, ghHost
}
if cfg != nil {
keys, err := cfg.Keys([]string{hostsKey})
if err == nil && len(keys) == 1 {
return keys[0], hostsKey
}
}
return github, defaultSource
}

@williammartin
Copy link
Member

I'm intrigued by the idea. A few questions jump to mind:

  • Can you point to some of the users that are running into this issue?
  • What opportunities would a user have to set this? gh config set? A prompt or flag on gh auth login?
  • Presumably if there were no "default" host we would use our existing behaviour?
  • Are there any gotchas you can think of, like installing of extensions?

Thanks!

@andyfeller
Copy link
Contributor Author

  • Can you point to some of the users that are running into this issue?

With v1.0.3 release of GitHub Copilot in the CLI, GitHub tenancy users are being advised to set GH_HOST or use --hostname for all usage because Copilot licensing is tied to the GitHub tenant.

Beyond that, I can only theorize GitHub Enterprise Server users with GitHub.com accounts using features like gh api are impacted.

  • What opportunities would a user have to set this? gh config set? A prompt or flag on gh auth login?

I think introducing a new gh auth command to select which existing authenticated host should be used for the default and adding a new field to the host configuration indicating the default.

Originally, I was considering gh config set but the problem is keeping this in sync with authenticated hosts. Then when you logout of that authenticated host, gh should revert to the native default host logic.

  • Presumably if there were no "default" host we would use our existing behaviour?

Yes!

  • Are there any gotchas you can think of, like installing of extensions?

This is a really good question and I actually wondered about this exact case! Reviewing the gh ext install manual, it's clear this doesn't follow the same patterns we see in other commands with [HOST/]OWNER/REPO format: 🤔

USAGE
  gh extension install <repository> [flags]

FLAGS
  --force        force upgrade extension, or ignore if latest already installed
  --pin string   pin extension to a release tag or commit ref

INHERITED FLAGS
  --help   Show help for command

EXAMPLES
  $ gh extension install owner/gh-extension
  $ gh extension install https://git.example.com/owner/gh-extension
  $ gh extension install .

Looking for commands that leverage RepoHost(), I think anything that doesn't show up here is likely a good candidate of being impacted:

$ grep -rl "RepoHost()" pkg/cmd | sort | uniq
pkg/cmd/cache/delete/delete.go
pkg/cmd/cache/shared/shared.go
pkg/cmd/extension/command.go
pkg/cmd/extension/http.go
pkg/cmd/extension/manager.go
pkg/cmd/factory/default_test.go
pkg/cmd/issue/close/close.go
pkg/cmd/issue/create/create.go
pkg/cmd/issue/delete/delete.go
pkg/cmd/issue/develop/develop.go
pkg/cmd/issue/list/http.go
pkg/cmd/issue/list/list.go
pkg/cmd/issue/lock/lock.go
pkg/cmd/issue/pin/pin.go
pkg/cmd/issue/reopen/reopen.go
pkg/cmd/issue/shared/lookup.go
pkg/cmd/issue/status/status.go
pkg/cmd/issue/transfer/transfer.go
pkg/cmd/issue/unpin/unpin.go
pkg/cmd/issue/view/http.go
pkg/cmd/label/create.go
pkg/cmd/label/delete.go
pkg/cmd/label/http.go
pkg/cmd/pr/checkout/checkout.go
pkg/cmd/pr/checkout/checkout_test.go
pkg/cmd/pr/checks/checks.go
pkg/cmd/pr/close/close_test.go
pkg/cmd/pr/create/create.go
pkg/cmd/pr/diff/diff.go
pkg/cmd/pr/list/http.go
pkg/cmd/pr/merge/http.go
pkg/cmd/pr/shared/commentable.go
pkg/cmd/pr/shared/editable.go
pkg/cmd/pr/shared/editable_http.go
pkg/cmd/pr/shared/finder.go
pkg/cmd/pr/shared/params_test.go
pkg/cmd/pr/shared/templates.go
pkg/cmd/pr/status/http.go
pkg/cmd/pr/status/status.go
pkg/cmd/release/create/http.go
pkg/cmd/release/delete/delete.go
pkg/cmd/release/edit/http.go
pkg/cmd/release/list/http.go
pkg/cmd/release/shared/fetch.go
pkg/cmd/repo/archive/http.go
pkg/cmd/repo/clone/clone.go
pkg/cmd/repo/create/create.go
pkg/cmd/repo/credits/credits.go
pkg/cmd/repo/delete/http.go
pkg/cmd/repo/deploy-key/add/http.go
pkg/cmd/repo/deploy-key/delete/http.go
pkg/cmd/repo/deploy-key/list/http.go
pkg/cmd/repo/edit/edit.go
pkg/cmd/repo/fork/fork.go
pkg/cmd/repo/garden/http.go
pkg/cmd/repo/rename/rename.go
pkg/cmd/repo/setdefault/setdefault.go
pkg/cmd/repo/sync/http.go
pkg/cmd/repo/sync/sync.go
pkg/cmd/repo/unarchive/http.go
pkg/cmd/repo/view/http.go
pkg/cmd/ruleset/check/check.go
pkg/cmd/ruleset/shared/http.go
pkg/cmd/ruleset/view/http.go
pkg/cmd/run/cancel/cancel.go
pkg/cmd/run/delete/delete.go
pkg/cmd/run/rerun/rerun.go
pkg/cmd/run/shared/artifacts.go
pkg/cmd/run/shared/shared.go
pkg/cmd/run/view/view.go
pkg/cmd/secret/list/list.go
pkg/cmd/secret/set/http.go
pkg/cmd/secret/set/set.go
pkg/cmd/variable/list/list.go
pkg/cmd/variable/set/http.go
pkg/cmd/variable/set/set.go
pkg/cmd/workflow/disable/disable.go
pkg/cmd/workflow/enable/enable.go
pkg/cmd/workflow/run/run.go
pkg/cmd/workflow/shared/shared.go

@ruudgoossens
Copy link

Given you are looking for use cases. Got an account on GHES and github.com and logged in to both. When creating a repository gh repo create and was creating repositories with the CLI. I expected that by using the gh auth switch command to switch to the GHES authorization it would also switch the default host. But found out that that was not the case as the prompt with organizations to create the repo in were still from github.com.

Summarizing, gh auth switch only switches authorizations within a host. There should also be a command for switching the (default) host.

Similarly, using gh api after a gh auth switch still reverts to the default github.com, only when logging out from github.com will it default to my GHES authorization.

> gh --version
gh version 2.53.0 (2024-07-17)
https://github.com/cli/cli/releases/tag/v2.53.0
> gh api /user --jq .login
ruudgoossens
> gh auth switch -h github.mydomain.com -u ruud
✓ Switched active account for github.mydomain.com to ruud
> gh api /user --jq .login
ruudgoossens
> gh auth logout -h github.com -u ruudgoossens
✓ Logged out of github.com account ruudgoossens
> gh api /user --jq .login
ruud

@williammartin
Copy link
Member

Dankjewel for the use case, it's definitely handy to have. Indeed gh auth switch is only about changing the active account on a particular host. Currently, if you are logged in to more than one host the only mechanism for targeting a host other than github.com is to use the GH_HOST environment variable.

If you could wave a magic wand for the CLI, what would the workflow around changing hosts look like for you? Cheers!

@andyfeller
Copy link
Contributor Author

xlinking cli/cli#10058 for discussion where GHES user expecting default host to be something other than github.com

@ruudgoossens
Copy link

I'm looking for a CLI way of switching between hosts, specifically between GHES and GHEC. CLI should keep record of the configured hosts (name and URL) and should request this when configurating an authentication. Given a certain authorization is always coupled to a certain host, I would expect that gh auth switch would set both active authentication and the host coupled to that authentication.

If this somehow interferes with other uses cases, a separate command would be acceptable, e.g., gh host switch. gh host switch should then also switch the host based on configured name or provide a menu of configured hosts to select the new active host.

@williammartin
Copy link
Member

Thanks for the details @ruudgoossens, useful to have your feedback.

I'm looking for a CLI way of switching between hosts, specifically between GHES and GHEC.

The current way to achieve this is to set GH_HOST.

I would expect that gh auth switch would set both active authentication and the host coupled to that authentication.

Yeh that would have been a sensible implementation if the CLI had previously had any form of switching a host via command but up to this point it's always been via GH_HOST, flag, or positional argument.

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

No branches or pull requests

3 participants