Skip to content

feat: add global --account flag to scope commands to a specific authenticated user - #3

Open
galamdring wants to merge 714 commits into
trunkfrom
feat/global-user-flag
Open

feat: add global --account flag to scope commands to a specific authenticated user#3
galamdring wants to merge 714 commits into
trunkfrom
feat/global-user-flag

Conversation

@galamdring

Copy link
Copy Markdown
Owner

Summary

Adds a --account persistent flag to the root command so any authenticated subcommand can be scoped to a specific GitHub account without requiring gh auth switch first.

Motivation

Users with multiple GitHub accounts (personal + work, multiple orgs) frequently need to run a single command as a different identity from the currently active one. Today that requires an explicit gh auth switch which changes global state. --account allows per-invocation identity selection with no side effects on other sessions.

What Changed

pkg/cmd/root/root.go

  • Added --account as a PersistentFlag on the root command so all subcommands inherit it.
  • In PersistentPreRunE, after the existing auth check, calls the new applyAccountFlag helper.
  • Added applyAccountFlag(cfg gh.Config, account string) error — a pure function that:
    1. No-ops when account is empty (default behaviour unchanged).
    2. Looks up DefaultHost() from the auth config.
    3. Calls UsersForHost(hostname) to get the list of authenticated users.
    4. Returns a descriptive error if the requested account is not in that list, with guidance:
      account "alice" is not authenticated on github.com. To add it run: gh auth login --hostname github.com
    5. On success, calls TokenForUser(hostname, account) then SetActiveToken(token, source) so all downstream HTTP calls in that invocation use the correct credential.

pkg/cmd/root/root_test.go (new)

  • 4 table-driven tests covering:
    • empty account (no-op)
    • account present and authenticated (token installed)
    • account not in the authenticated list (descriptive error)
    • multiple accounts, correct one selected

Flag Name Choice

--user was the natural first choice but conflicts with local flags already on several subcommands (codespace list, auth token, run list, secret list). Cobra panics at AddCommand when a persistent root flag shares a name with a local child flag. --account has zero conflicts across pkg/cmd/.

Testing

go test ./pkg/cmd/root/... -run Test_applyAccountFlag   # 4/4 pass
go test ./...                                           # zero failures

patrickwehbe and others added 30 commits July 2, 2026 14:25
Co-authored-by: Patrick Wehbe <patrick.wehbe.applications@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Kynan Ware <47394200+BagToad@users.noreply.github.com>
* Validate Jupyter Server URLs

* Validate Jupyter Server URLs: address reviews

* Validate Jupyter Server URLs: address test reviews

* Validate Jupyter Server URLs: address test reviews
The workflow was reverted to source APPLE_DEVELOPER_INSTALLER_ID from
vars.APPLE_DEVELOPER_INSTALLER_ID, but the docs snippet still showed
vars.MAC_APP_SIGNING_IDENTITY.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The note claimed the step now passes vars.MAC_APP_SIGNING_IDENTITY, but
the workflow still passes the (unset) vars.APPLE_DEVELOPER_INSTALLER_ID.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prevents word-splitting/globbing if the keychain path ever contains
spaces or glob characters.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 3-second timeout doesn't leave enough time to respond to an
interactive unlock prompt (password entry, biometric confirmation,
etc.), causing gh to give up before the user can react.

Fixes cli#11005
Co-authored-by: Babak K. Shandiz <babakks@github.com>
Bring the release deep-dive in line with the final branch state:
site steps gated on production, createrepo/reprepro gate on
environment instead of GPG_SIGN, dropped github.token fallback,
quoted keychain paths, and documented the script/release --dry-run
default. Also restore the reprepro env: key that was dropped when
GPG_SIGN was removed, which had left the workflow YAML invalid.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bumps [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/charmbracelet/lipgloss/releases)
- [Commits](charmbracelet/lipgloss@v2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: charm.land/lipgloss/v2
  dependency-version: 2.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.18.6 to 1.19.0.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Commits](klauspost/compress@v1.18.6...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
…d/lipgloss/v2-2.0.5

chore(deps): bump charm.land/lipgloss/v2 from 2.0.4 to 2.0.5
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.81.1 to 1.82.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](grpc/grpc-go@v1.81.1...v1.82.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.82.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
…lang.org/grpc-1.82.0

chore(deps): bump google.golang.org/grpc from 1.81.1 to 1.82.0
…m/klauspost/compress-1.19.0

chore(deps): bump github.com/klauspost/compress from 1.18.6 to 1.19.0
Bumps [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) from 2.0.7 to 2.0.8.
- [Release notes](https://github.com/charmbracelet/bubbletea/releases)
- [Commits](charmbracelet/bubbletea@v2.0.7...v2.0.8)

---
updated-dependencies:
- dependency-name: charm.land/bubbletea/v2
  dependency-version: 2.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.36.2 to 4.36.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@8aad20d...54f647b)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.38.0 to 0.39.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](golang/text@v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.46.0 to 0.47.0.
- [Commits](golang/sys@v0.46.0...v0.47.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Replace the inline decision tree with the shared skills-driven approach
used in desktop/desktop. The workflow now fetches triage instructions from
desktop/gh-cli-and-desktop-shared-workflows at runtime, uses a GitHub App
token for auth, and always suggests labels at medium confidence or lower
so all suggestions require maintainer approval.

Key changes:
- Add repos toolset and allowed-repos for cross-repo skill loading
- Add min-integrity: none for reading untrusted issue content
- Add github-app safe-output with CLI_TRIAGE_APP secret refs
- Replace inline decision tree with 5-step skills-driven flow
- Keep duplicate label (cli/cli has one, unlike desktop)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Draft: issue-intents agentic issue triage (starting point for discussion)
Add copilot-requests: write permission so the workflow uses the built-in
GitHub Actions token for LLM calls, removing the need for a separate
COPILOT_GITHUB_TOKEN secret.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use Actions token for Copilot inference in issue-triage workflow
Bumps [github/gh-aw-actions/setup](https://github.com/github/gh-aw-actions) from 0.81.6 to 0.82.2.
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](github/gh-aw-actions@ba6380c...3fac1cf)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions/setup
  dependency-version: 0.82.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
…d/bubbletea/v2-2.0.8

chore(deps): bump charm.land/bubbletea/v2 from 2.0.7 to 2.0.8
williammartin and others added 28 commits August 7, 2026 16:45
Clarify what belongs in the PR template's testing section
…t-ci

Bump golangci-lint in CI to v2.12.2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Bumps [github/gh-aw-actions/setup-cli](https://github.com/github/gh-aw-actions) from 0.83.4 to 0.85.4.
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](github/gh-aw-actions@e89c65e...2709137)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions/setup-cli
  dependency-version: 0.84.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
…ns/attest-4.2.2

chore(deps): bump actions/attest from 4.2.1 to 4.2.2
…/login-3.0.1

chore(deps): bump azure/login from 3.0.0 to 3.0.1
…l-actions-a8bbb0c234

chore(deps): bump the codeql-actions group across 1 directory with 3 updates
…b/gh-aw-actions/setup-cli-0.84.2

chore(deps): bump github/gh-aw-actions/setup-cli from 0.83.4 to 0.85.4
…tput

Fix project item-add output for non-TTY
Add aw-actions group to dependabot configuration
Bumps the aw-actions group with 2 updates: [github/gh-aw-actions/setup](https://github.com/github/gh-aw-actions) and [github/gh-aw-actions/setup-cli](https://github.com/github/gh-aw-actions).


Updates `github/gh-aw-actions/setup` from 0.83.4 to 0.86.1
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](github/gh-aw-actions@v0.83.4...8914f47)

Updates `github/gh-aw-actions/setup-cli` from 0.85.4 to 0.86.1
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](github/gh-aw-actions@2709137...8914f47)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions/setup
  dependency-version: 0.86.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: aw-actions
- dependency-name: github/gh-aw-actions/setup-cli
  dependency-version: 0.86.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: aw-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
…tions-0509bfe7a3

chore(deps): bump the aw-actions group with 2 updates
Matches the convention already used by internal/prompter, pkg/cmd/run/shared,
and pkg/cmd/workflow/shared for their test helper files.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Config from GIT_CONFIG_COUNT and GIT_CONFIG_PARAMETERS is command line scope,
which outranks both the global and system files, so pointing GIT_CONFIG_GLOBAL
at an empty file was not enough on its own. An inherited safe.bareRepository=explicit
made git refuse to open the bare fixtures at all.

Replaces the copy of this helper in each of the two packages that needed it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
go-gh reads GH_TOKEN and friends ahead of any stored config, so isolating the
config file left tests authenticated for anyone with a token exported. Nine
packages failed as a result.

The token test set its own env vars before building the config, which the
clearing would undo, so it now sets them after.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The helper only ever produced an empty config, so tests needing populated hosts
had to reach for the mock instead and lost the env isolation that comes with it.

Test_mightBeGHESUser was one of those. Its cases named "no env vars" never
cleared any, so they failed whenever GH_ENTERPRISE_TOKEN or GH_HOST was set.
Its table now holds config strings rather than prebuilt configs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Neither mock constructor had a doc comment, so nothing signalled which of the
three to reach for. Each now says what it does and points at the other.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
NewBlankConfig and NewFromString gave no hint that what came back was a mock,
which made them the default choice even where the real config was wanted. Every
other mock constructor in the repo already announces itself, as in NewMockPrompter
and NewMockFinder.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Isolate tests from local machine's auth and git configuration
When multiple GitHub accounts are configured for the same host, gh always
uses the globally active account's token regardless of which org or user
owns the current repo. This causes commands to silently authenticate as
the wrong user.

This change adds an owner-to-user mapping stored in hosts.yml, and
automatically selects the correct token based on the repo owner resolved
from git remotes at HTTP client construction time. A new command
'gh auth set-user --owner <owner> <username>' manages the mappings.

Fixes cli#12885
…ection

Adds a --account flag to the root command that is inherited by every
authenticated subcommand. When specified, the flag validates that the
given account is currently authenticated for the default host and
overrides the active token for the duration of that command.

If the account is not authenticated, an error is returned with direction
to add it via: gh auth login --hostname <host>

Changes:
- pkg/cmd/root/root.go: register --account as a persistent flag,
  invoke applyAccountFlag from PersistentPreRunE after auth check,
  add applyAccountFlag helper that validates + overrides the active token
- pkg/cmd/root/root_test.go: table-driven tests for applyAccountFlag
  covering missing account, error message content, single valid account,
  and multi-user disambiguation
NewIsolatedTestConfig now takes a cfgString param, and HttpClientFunc now
takes a remotesFunc param (added in the per-owner account mapping commit).
Fork-added tests were never updated for these, so they failed to compile
once rebased onto the current upstream/trunk.
The scheduled rebase onto upstream/trunk has been failing every week for
the last 2.5 months on the same unresolved conflict, with nothing but a
red check nobody was watching. Abort cleanly on conflict and file (or
update) a tracking issue summarizing what needs manual resolution.
@galamdring
galamdring force-pushed the feat/global-user-flag branch from 0627792 to 157db71 Compare August 13, 2026 22:47

git rebase --abort
exit 1

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.