Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@anuraaga
Copy link
Contributor

@anuraaga anuraaga commented May 29, 2025

Fixes #10136

I have been following this issue for a while but finally tried checking the code. It seemed pretty simple to allow the GH_CONFIG_DIR switching mechanism to work, and the change seems easy to reason about to me so tried sending a PR.

Note that when using login, we set the username-keyed token

setErr = keyring.Set(keyringServiceName(hostname), username, token)

so as far as I'm aware, there aren't really any gotchas, and in fact we could potentially remove the fallback to "" - I left it for safety in case there are still some cases not covered by getting the token for the active user. If there are old versions that didn't populate the username-keyed value to keyring when logging in, then I guess they may rely on the fallback.

Copilot AI review requested due to automatic review settings May 29, 2025 03:17
@anuraaga anuraaga requested a review from a team as a code owner May 29, 2025 03:17
@anuraaga anuraaga requested a review from andyfeller May 29, 2025 03:17
@anuraaga anuraaga temporarily deployed to cli-automation May 29, 2025 03:17 — with GitHub Actions Inactive
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label May 29, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Fixes token lookup to prefer an active user’s keyring entry before falling back to the blank key, and updates tests to cover and stub that behavior.

  • Prioritize user-specific token in TokenFromKeyring
  • Add new test to verify active-user token selection
  • Stub ActiveToken in API tests for consistent behavior

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
internal/config/config.go Added logic in TokenFromKeyring to try ActiveUser key first
internal/config/auth_config_test.go New test TestTokenFromKeyringActiveUserNotBlankUser
pkg/cmd/api/api_test.go Introduced stubAuthConfig and updated Config closure signature for API tests
Comments suppressed due to low confidence (4)

pkg/cmd/api/api_test.go:1346

  • [nitpick] The name stubAuthConfig is ambiguous; consider renaming to mockAuthConfig or fakeAuthConfig for clearer intent.
type stubAuthConfig struct {

internal/config/auth_config_test.go:45

  • [nitpick] Consider renaming this to TestTokenFromKeyring_PrioritizesActiveUserToken to more explicitly describe the expected behavior.
func TestTokenFromKeyringActiveUserNotBlankUser(t *testing.T) {

internal/config/auth_config_test.go:73

  • Add a test case for when an active user is set but no user-specific keyring entry exists, ensuring it falls back to the default (blank) token.
token, err = authCfg.TokenFromKeyring("github.com")

pkg/cmd/api/api_test.go:1368

  • The named return parameters cfg and err aren’t used and add noise; revert to the unnamed signature func() (gh.Config, error) to match surrounding tests.
Config: func() (cfg gh.Config, err error) {

// TokenFromKeyring will retrieve the auth token for the given hostname,
// only searching in encrypted storage.
func (c *AuthConfig) TokenFromKeyring(hostname string) (string, error) {
if user, err := c.ActiveUser(hostname); err == nil && user != "" {
Copy link
Member

@williammartin williammartin May 29, 2025

Choose a reason for hiding this comment

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

I don't have time to review this properly @andyfeller but as the person that introduced 🌚 and triaged the original issue, I'm pretty sure this is conceptually what I had in mind as a first attempt at fixing this.

This wasn't marked as help-wanted but I do think its pretty bad, so I would welcome us prioritising this fix. I actually brought up wanting to spend some time fixing multi-account sharp edges this week with @mxie

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @williammartin - just wondering if it's possible for anyone to review this? I think there's still more that can be done to generally improve UX of multi-auth, but hopefully this fix is contained and easy enough to reason about to make some steps towards that.

Copy link
Member

Choose a reason for hiding this comment

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

Mainly just a matter of priority. We're all meeting offsite this week so there's been a lot of travelling. Would love for you to drop your thoughts on improving multi-auth UX in a new discussion. I also have lots of thoughts, and again, it's really a matter of having the evidence to prioritise it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hopefully finished with offsites and such - would it be possible to get a review on this? I get priority for feature requests, but this is a bug fix so seems like it should generally be prioritized...

Copy link
Member

Choose a reason for hiding this comment

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

Thank you, @williammartin, for picking up the slack 🙇 Having returned from offiste and trips, I'm catching up on this PR now.

@williammartin
Copy link
Member

williammartin commented Jun 17, 2025

Acceptance Criteria

Given I have two accounts on a single github host
And Given I have each of these accounts as the active user in separate hosts.yml files
When I set GH_CONFIG_DIR to either of the files
And When I run gh api /user .login
Then I see the active user is correct as per the hosts.yml file

# Current version
➜ gh version
gh version 2.74.1 (2025-06-10)
https://github.com/cli/cli/releases/tag/v2.74.1

# auth status
➜ gh auth status --hostname github.com
github.com
  ✓ Logged in to github.com account wilmartin_microsoft (keyring)
  - Active account: true
  - Git operations protocol: https
  - Token: gho_************************************
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

  ✓ Logged in to github.com account williammartin (keyring)
  - Active account: false
  - Git operations protocol: https
  - Token: gho_************************************
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

# Current hosts.yml
➜ cat ~/.config/gh/hosts.yml
github.com:
    git_protocol: https
    users:
        williammartin: {}
        wilmartin_microsoft:
    user: wilmartin_microsoft

# Hit the API to see the token in use
➜ gh api /user --jq .login | cat
wilmartin_microsoft

# Adjust the hosts.yml (as if swapping GH_CONFIG_DIR)
➜  cat ~/.config/gh/hosts.yml
github.com:
    git_protocol: https
    users:
        williammartin: {}
        wilmartin_microsoft:
    user: williammartin
    
# Hit the API to see that the same (wrong token) is in use
➜ gh api /user --jq .login | cat
wilmartin_microsoft

# Build this branch
➜  cli git:(active-token-user) ✗ make
go build -trimpath -ldflags "-X github.com/cli/cli/v2/internal/build.Date=2025-06-17 -X github.com/cli/cli/v2/internal/build.Version=v2.74.0-7-g8deae3038 " -o bin/gh ./cmd/gh

# Set that it uses the correct token
➜ ./bin/gh api /user --jq .login | cat
williammartin

# And that auth status has correctly updated
➜ gh auth status --hostname github.com
github.com
  ✓ Logged in to github.com account williammartin (keyring)
  - Active account: true
  - Git operations protocol: https
  - Token: gho_************************************
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

  ✓ Logged in to github.com account wilmartin_microsoft (keyring)
  - Active account: false
  - Git operations protocol: https
  - Token: gho_************************************
  - Token scopes: 'gist', 'read:org', 'repo', 'workflow'

Copy link
Member

@williammartin williammartin left a comment

Choose a reason for hiding this comment

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

@anuraaga this is functionally correct but I think that perhaps we should approach this slightly differently. I think maybe we should take the logic in TokenFromKeyring and push it into ActiveToken. I think the ActiveToken / ActiveUser parallel is stronger and then maybe I'll come back later and start renaming things like TokenFromKeyring to indicate their legacy, or fallback nature.

Is there some reason you think this wouldn't work?

@anuraaga
Copy link
Contributor Author

Thanks @williammartin - unless I'm missing something since this is all in /internal/ there wouldn't even need to be renames for legacy reasons, we can just go for the end state in one shot. If the current separation is desired for readability reasons that seems fine, if pushing up is clearer that seems fine too. I can tweak this PR if there's any preference.

@williammartin
Copy link
Member

@anuraaga the renames would be for our maintainability. I just think I need to poke around a bit more to decide exactly what name I'd want, which is why I'm not suggesting you do it. I would like you to try and move the logic into ActiveToken so that it does the ActiveUser -> TokenFromKeyringForUser -> Fallback to TokenFromKeyring.

@anuraaga
Copy link
Contributor Author

Thanks @williammartin - moved the logic to ActiveToken, hopefully it looks ok

- ensure test user tokens are different from unkeyed token
- ensure assertion expected / actual are in correct order
authCfg := newTestAuthConfig(t)
require.NoError(t, keyring.Set(keyringServiceName("github.com"), "", "test-token"))
require.NoError(t, keyring.Set(keyringServiceName("github.com"), "test-user1", "test-token"))
require.NoError(t, keyring.Set(keyringServiceName("github.com"), "test-user1", "test-token1"))
Copy link
Member

@williammartin williammartin Jun 20, 2025

Choose a reason for hiding this comment

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

This isn't really representative of the most common case. In nearly all cases the token in the empty username keyring entry will match one of the username keyring entries. The previous test is much more likely to be the case.

@andyfeller
Copy link
Member

Thank you for your patience, @anuraaga; my sincere apologies for not following up sooner! 🙇

I made a minor enhancement to one of the tests to differentiate the tokens and swapped order of test assertion. Just seeing CI checks pass for final review.

After discussing my previous change to the test, I'm restoring the previous keyring setup to reflect the specific situation.

I added clarifying comments to help the next reviewer.
@williammartin
Copy link
Member

Think this is probably ready to go @andyfeller ?

Copy link
Member

@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.

You must ship it if squirrel tells you to ship it

@andyfeller andyfeller merged commit e5913fe into cli:trunk Jun 27, 2025
10 checks passed
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jul 27, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [cli/cli](https://github.com/cli/cli) | minor | `v2.74.2` -> `v2.76.1` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>cli/cli (cli/cli)</summary>

### [`v2.76.1`](https://github.com/cli/cli/releases/tag/v2.76.1): GitHub CLI 2.76.1

[Compare Source](cli/cli@v2.76.0...v2.76.1)

#### `gh pr create` regression fix

This release fixes a regression introduced in `v2.76.0` where organization teams were retrieved outside of intentional use cases.  This caused problems for GitHub Enterprise Server users using the GitHub Actions automatic token that does not have access to organization teams.

For more information, see cli/cli#11360

#### What's Changed

##### 🐛 Fixes

- Fix: `gh pr create`, only fetch teams when reviewers contain a team  by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11361

##### 📚 Docs & Chores

- add tenancy aware for san matcher by [@&#8203;ejahnGithub](https://github.com/ejahnGithub) in cli/cli#11261
- Run Lint and Tests on `push` to `trunk` branch by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11325
- update ownership of pkg/cmd/release/shared/ by [@&#8203;ejahnGithub](https://github.com/ejahnGithub) in cli/cli#11326
- Automate spam issue detection by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11316
- Improve `api` `--preview` docs by [@&#8203;jsoref](https://github.com/jsoref) in cli/cli#11274
- Incorporate govulncheck into workflows by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11332
- chore(deps): bump advanced-security/filter-sarif from 1.0.0 to 1.0.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11298
- chore(deps): bump github.com/sigstore/sigstore-go from 1.0.0 to 1.1.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11307

**Full Changelog**: cli/cli@v2.76.0...v2.76.1

### [`v2.76.0`](https://github.com/cli/cli/releases/tag/v2.76.0): GitHub CLI 2.76.0

[Compare Source](cli/cli@v2.75.1...v2.76.0)

#### :copilot: Copilot Coding Agent Support

GitHub Copilot Pro+ and Copilot Enterprise subscribers can now assign issues to GitHub Copilot during issue creation using:

- Command-line flag: `gh issue create --assignee @&#8203;copilot`
- Launching web browser: `gh issue create --assignee @&#8203;copilot --web`
- Or interactively selecting `Copilot (AI)` as assignee in `gh issue create` metadata

For more details, refer to [the full changelog post for Copilot coding agent](https://github.blog/changelog/2025-05-19-github-copilot-coding-agent-in-public-preview/).

#### What's Changed

##### ✨ Features

- Assign Copilot during `gh issue create` by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11279
- Display immutable field in `release view` command by [@&#8203;bdehamer](https://github.com/bdehamer) in cli/cli#11251

##### 🐛 Fixes

- FIX: Do not fetch logs for skipped jobs by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11312
- Transform `extension` and `filename` qualifiers into `path` qualifier for web code search by [@&#8203;samcoe](https://github.com/samcoe) in cli/cli#11211

##### 📚 Docs & Chores

- FIX: Workflow does not contain permissions by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11322
- Add automated feature request response workflow by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11299

**Full Changelog**: cli/cli@v2.75.1...v2.76.0

### [`v2.75.1`](https://github.com/cli/cli/releases/tag/v2.75.1): GitHub CLI 2.75.1

[Compare Source](cli/cli@v2.75.0...v2.75.1)

#### What's Changed

##### 🐛 Fixes

- Ensure hostnames are visible in CLI website by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11295
- Revert "Fix: `gh pr create` prioritize `--title` and `--body` over `--fill` when `--web` is present" by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11300

##### 📚 Docs & Chores

- Ensure go directive is always .0 version in bump by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11259
- Minor (1-word) documentation typo in generated `~/.config/gh/config.yml` by [@&#8203;kurahaupo](https://github.com/kurahaupo) in cli/cli#11246
- Automate closing of stale issues by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11268
- Filter the `third-party/` folder out of CodeQL results by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11278
- Exclude `third-party` source from golangci-lint by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11293

##### :dependabot: Dependencies

- Bump Go to 1.24.5 by [@&#8203;github-actions](https://github.com/github-actions)\[bot] in cli/cli#11255
- chore(deps): bump github.com/sigstore/protobuf-specs from 0.4.3 to 0.5.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11263
- chore(deps): bump golang.org/x/term from 0.32.0 to 0.33.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11266
- chore(deps): bump golang.org/x/sync from 0.15.0 to 0.16.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11264
- chore(deps): bump golang.org/x/text from 0.26.0 to 0.27.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11265
- chore(deps): bump golang.org/x/crypto from 0.39.0 to 0.40.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in cli/cli#11275

#### New Contributors

- [@&#8203;kurahaupo](https://github.com/kurahaupo) made their first contribution in cli/cli#11246
- [@&#8203;github-actions](https://github.com/github-actions)\[bot] made their first contribution in cli/cli#11255

**Full Changelog**: cli/cli@v2.75.0...v2.75.1

### [`v2.75.0`](https://github.com/cli/cli/releases/tag/v2.75.0): GitHub CLI 2.75.0

[Compare Source](cli/cli@v2.74.2...v2.75.0)

#### What's Changed

##### ✨ Features

- init release verify subcommands  by [@&#8203;ejahnGithub](https://github.com/ejahnGithub) in cli/cli#11018
- Embed Windows resources (VERSIONINFO) during build by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11048
- Support `--no-repos-selected` on `gh secret set` by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11217

##### 🐛 Fixes

- Fix: `gh pr create` prioritize `--title` and `--body` over `--fill` when `--web` is present by [@&#8203;dankrzeminski32](https://github.com/dankrzeminski32) in cli/cli#10547
- fix: get token for active user instead of blank if possible by [@&#8203;anuraaga](https://github.com/anuraaga) in cli/cli#11038
- Use Actions API to retrieve job run logs as a fallback mechanism  by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11172
- Fix query object state mutation during pagination by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11244
- Handle `HTTP 404` when deleting remote branch in `pr merge` by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11234

##### 📚 Docs & Chores

- chore: fix function name by [@&#8203;jinjingroad](https://github.com/jinjingroad) in cli/cli#11149
- chore: update Go version to 1.24 in devcontainer configuration and docs by [@&#8203;tMinamiii](https://github.com/tMinamiii) in cli/cli#11158
- Ensure lint workflow checks whether 3rd party license and code is up to date by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11047
- docs: install\_linux.md: add Solus linux install instructions by [@&#8203;chax](https://github.com/chax) in cli/cli#10823
- Fix missing newline in install\_linux.md by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11160
- Ensure automation uses pinned go-licenses version by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11161
- Add `workflow_dispatch` support to MR Help Wanted check by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11179
- Remove unused `GH_TOKEN` env variable from workflow by [@&#8203;BagToad](https://github.com/BagToad) in cli/cli#11190
- Add workflow to automate go version bumping by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11189
- Fix inconsistent use of tabs and spaces by [@&#8203;Stefan-Heimersheim](https://github.com/Stefan-Heimersheim) in cli/cli#11194
- Decouple arg parsing from MR finder by [@&#8203;babakks](https://github.com/babakks) in cli/cli#11192
- docs: consistently use `apt` in installation instructions by [@&#8203;tklauser](https://github.com/tklauser) in cli/cli#11216
- Ensure bump go script has git user configured by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11229
- Inject token into bump-go workflow by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11233
- Reinstating Primer Style CLI content within `cli/cli` repository by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11060
- Add setup-go to bump-go workflow by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11237
- Ensure GoReleaser does not break on Mac OS and Linux when skipping Windows `.rsyso` generation script by [@&#8203;andyfeller](https://github.com/andyfeller) in cli/cli#11257

##### :dependabot: Dependencies

- Bump all dependencies except dev-tunnels by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11203
- Update microsoft dev-tunnels to v0.1.13 by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11205
- Consume dependabot minor versions for go modules by [@&#8203;williammartin](https://github.com/williammartin) in cli/cli#11213

#### New Contributors

- [@&#8203;jinjingroad](https://github.com/jinjingroad) made their first contribution in cli/cli#11149
- [@&#8203;tMinamiii](https://github.com/tMinamiii) made their first contribution in cli/cli#11158
- [@&#8203;chax](https://github.com/chax) made their first contribution in cli/cli#10823
- [@&#8203;dankrzeminski32](https://github.com/dankrzeminski32) made their first contribution in cli/cli#10547
- [@&#8203;anuraaga](https://github.com/anuraaga) made their first contribution in cli/cli#11038
- [@&#8203;Stefan-Heimersheim](https://github.com/Stefan-Heimersheim) made their first contribution in cli/cli#11194

**Full Changelog**: cli/cli@v2.74.2...v2.75.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC42Mi4xIiwidXBkYXRlZEluVmVyIjoiNDAuNjIuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
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

None yet

Development

Successfully merging this pull request may close these issues.

Account incorrectly reported active in gh auth status

4 participants