Skip to content

Conversation

@benjlevesque
Copy link
Contributor

@benjlevesque benjlevesque commented Aug 20, 2025

This PR adds a --json flag to the gh auth status command.
--jq and --template are also available

Resolves #8637
Acceptance criteria: #8637 (comment)

@benjlevesque benjlevesque changed the title Fix missing assertions Add JSON output to gh auth status Aug 20, 2025
@benjlevesque benjlevesque marked this pull request as ready for review August 20, 2025 21:09
@benjlevesque benjlevesque requested a review from a team as a code owner August 20, 2025 21:09
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label Aug 20, 2025
@evilhamsterman
Copy link

This look great to me!

@BagToad BagToad self-requested a review August 25, 2025 14:58
@BagToad BagToad requested a review from babakks August 25, 2025 16:26
Copy link
Member

@babakks babakks left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, @benjlevesque! 🙏

I haven't yet fully reviewed it, just had a comment on the -t conflict case to trigger a discussion.

@babakks babakks self-requested a review September 5, 2025 08:20
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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Member

@babakks babakks left a comment

Choose a reason for hiding this comment

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

Thanks for the update! 🙏 I'm asking for changes because there's a bug and also the showToken usage is still confusing.

Comment on lines 76 to 89
if e.Login != "" {
sb.WriteString(fmt.Sprintf(" %s Timeout trying to log in to %s account %s (%s)\n", cs.Red("X"), e.Host, cs.Bold(e.Login), e.TokenSource))
} else {
sb.WriteString(fmt.Sprintf(" %s Timeout trying to log in to %s using token (%s)\n", cs.Red("X"), e.Host, e.TokenSource))
}
activeStr := fmt.Sprintf("%v", e.Active)
sb.WriteString(fmt.Sprintf(" - Active account: %s\n", cs.Bold(activeStr)))

case authStateError:
if e.Login != "" {
sb.WriteString(fmt.Sprintf(" %s Failed to log in to %s account %s (%s)\n", cs.Red("X"), e.Host, cs.Bold(e.Login), e.TokenSource))
} else {
sb.WriteString(fmt.Sprintf(" %s Failed to log in to %s using token (%s)\n", cs.Red("X"), e.Host, e.TokenSource))
}
Copy link
Member

Choose a reason for hiding this comment

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

I tried gh auth status with and without --json, and noticed the output is not the same (i.e. error field was empty for invalid entries). The reason is authEntry.Error is never assigned in buildEntry, and rather we print the error here in display stage.

So, let's move these error messages to buildEntry and populate authEntry.Error with them, and then here we can just print the authEntry.Error value.

Copy link
Contributor Author

@benjlevesque benjlevesque Sep 16, 2025

Choose a reason for hiding this comment

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

good catch! I updated the test to cover the JSON output of the error field, plus added a missing test on the token auth.
Also, I refactored the String function, which was hard to read, without the switch/case.

I chose to keep a minimal error in the JSON, and append the formatted details (login, host and token source) only for the regular output, as all of these information are already available in the JSON. Also in order to keep formatting details out of the buildEntry function... Wdyt?

@babakks
Copy link
Member

babakks commented Sep 23, 2025

@benjlevesque, as an update we decided to slightly change the JSON output structure to make room for future extensibility. The PR looks very good and I really appreciate your work! 🍻

I'm going to apply the changes on this PR and then ask @BagToad for a review.

@benjlevesque
Copy link
Contributor Author

@benjlevesque, as an update we decided to slightly change the JSON output structure to make room for future extensibility. The PR looks very good and I really appreciate your work! 🍻

I'm going to apply the changes on this PR and then ask @BagToad for a review.

got it, no problem. Just out of curiosity, what are the changes you decided?

@babakks
Copy link
Member

babakks commented Sep 23, 2025

It's about avoiding the top-level object being a dynamic-key map. The problem with a dynamic-key map (or an array) at the top-level is that you cannot extend them in the future (e.g. by adding a new key/value pair) without the risk of breaking automation scripts. So, a safe/forward-compatible approach is something like this:

{
  "hosts": {
    "github.com": [/*...*/],
    "another.host": [/*...*/],
  }
}

This allows us to add more top-level fields next to hosts in the future without breaking the automated scripts.

Another merit is that users are now free of specifying individual entry fields (i.e. login, token, etc.) and instead they just provide --json hosts. The only gotcha is with the token, field, for which we decided to respect the --show-token flag, and drop it by default.

@benjlevesque
Copy link
Contributor Author

I see, this seems like a good idea 👍

Signed-off-by: Babak K. Shandiz <babakks@github.com>
Signed-off-by: Babak K. Shandiz <babakks@github.com>
Copy link
Member

@babakks babakks left a comment

Choose a reason for hiding this comment

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

Approve to clear the last request for changes. But this has yet to be reviewed by @BagToad.

@babakks babakks requested review from BagToad and removed request for BagToad September 23, 2025 14:44
Copy link
Member

@BagToad BagToad left a comment

Choose a reason for hiding this comment

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

Nice PR! LGTM

@srid
Copy link

srid commented Sep 24, 2025

This PR works great for a project of mine, where I just want a programmatic way to tell if gh CLI has signed in:

❯ gh auth status --json hosts
{
  "hosts": {
    "github.com": [
      {
        "state": "success",
        "active": true,
        "host": "github.com",
        "login": "srid",
        "tokenSource": "keyring",
        "scopes": "gist, read:org, repo",
        "gitProtocol": "ssh"
      }
    ]
  }
}

I suppose checking for "active" to be true is what I need.

Signed-off-by: Babak K. Shandiz <babakks@github.com>
@babakks
Copy link
Member

babakks commented Sep 25, 2025

This PR works great for a project of mine, where I just want a programmatic way to tell if gh CLI has signed in:

@srid, I'm not sure what exactly you mean by signed in (e.g. as in having a valid/working token, or just have signed in at some point), but please note that:

  • auth status is not a static command; it talks to the API to make sure the tokens are still valid.
  • seeing active: true does not mean the token is valid/working. Rather it just means gh will use that user's token by default, unless you run gh auth switch to make another user active. I can see the terminology is a bit confusing here.
  • the state field should be the only source of truth if you need to find a valid/working token (i.e. state: success).

@babakks babakks requested a review from BagToad September 25, 2025 10:02
@srid
Copy link

srid commented Sep 25, 2025

Ah, I just noticed that hosts."github.com" is a list.

  • Is there exactly one active token at a time?

If so, how can the JSON be restructured to reliably get that active token? In the current schema, it is possible for arbitrary number of tokens to be active, since it is just a list.

@srid
Copy link

srid commented Sep 25, 2025

I'm not sure what exactly you mean by signed in (e.g. as in having a valid/working token

Basically, I want to make sure that the user has gh auth login'ed once, so that running https://github.com/basecamp/gh-signoff will succeed.

@babakks
Copy link
Member

babakks commented Sep 25, 2025

  • Is there exactly one active token at a time?

Yes, only one entry per hostname can be active. You can run the command with --active flag to limit the results to just the active entries. However, if there are more than one host, you'd get one active entry per each. You can also use --hostname <HOST> to filter the only one you're interested in.

UPDATE: if you already know the hostname, technically you can try gh auth token --hostname <HOST> which will return the token for the active user for the given host. The upside is that there'll be no API roundtrip, but the downside is that you're going to get the user's token, which depending on your use case could be okay or not. I'd say you better off using auth status to be on the safe side and not doing anything that might be perceived as malicious to your users.

@BagToad BagToad merged commit b76bc77 into cli:trunk Sep 25, 2025
11 checks passed
@chedoe
Copy link

chedoe commented Sep 29, 2025

#11822

chedoe

This comment was marked as spam.

tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Oct 10, 2025
This MR contains the following updates:

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

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.81.0`](https://github.com/cli/cli/releases/tag/v2.81.0): GitHub CLI 2.81.0

[Compare Source](cli/cli@v2.80.0...v2.81.0)

#### Support for GitHub Release Attestations

This release introduces the `release verify` and `release verify-asset` commands for verifying GitHub Release attestations. Part of the Immutable Releases initiative, a release attestation provides a signed, timestamped binding between a release, its git tag, and any associated assets. These new commands provide a convenient way to verify the integrity of an immutable release against its attestation.

- Verify the latest release has a valid attestation: `gh release verify`
- Verify a specific release by tag: `gh release verify v1.2.3`
- Verify an asset from the latest release: `gh release verify-asset my-asset.zip`
- Verify a local asset file originated from a specific release: `gh release verify-asset v1.2.3 my-asset.zip`

These commands help ensure that releases and their assets are authentic and haven’t been tampered with, providing an additional layer of security for your software supply chain.

#### `gh auth status` Supports JSON Output

This release adds support for the `--json` flag in `gh auth status`. Run `gh auth status --help` for more information and usage examples.

#### What's Changed

##### ✨ Features

- Add alias `co` for `pr checkout` by [@&#8203;babakks](https://github.com/babakks) in [#&#8203;11804](cli/cli#11804)
- Add JSON output to `gh auth status` by [@&#8203;benjlevesque](https://github.com/benjlevesque) in [#&#8203;11544](cli/cli#11544)
- `release verify`  and `release verify-asset` are now visible by [@&#8203;ejahnGithub](https://github.com/ejahnGithub) in [#&#8203;11801](cli/cli#11801)

##### 🐛 Fixes

- Fix no tagname logic for  release verify-asset  by [@&#8203;ejahnGithub](https://github.com/ejahnGithub) in [#&#8203;11798](cli/cli#11798)

##### 📚 Docs & Chores

- refactor: use strings.FieldsFuncSeq to reduce memory allocations by [@&#8203;juejinyuxitu](https://github.com/juejinyuxitu) in [#&#8203;11805](cli/cli#11805)

#### New Contributors

- [@&#8203;juejinyuxitu](https://github.com/juejinyuxitu) made their first contribution in [#&#8203;11805](cli/cli#11805)

**Full Changelog**: <cli/cli@v2.80.0...v2.81.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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzIuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMi41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
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.

gh auth status should have a JSON output option

7 participants