cmd/gist-logs: On 404, the PAT probably needs more permissions

- This 404 error is from GitHub, and GitHub doesn't give us any more
  informations about scopes for the gist endpoint (for some reason). But we can
  safely assume, as it happens a lot, that "Error: Not Found" (404) is because
  the user hasn't granted their `HOMEBREW_GITHUB_API_TOKEN` the `gist` scope.

Before:

```shell
$ HOMEBREW_GITHUB_API_TOKEN=<token_without_gist_scope> brew gist-logs -p logrotate
Error: Not Found
```

After:

```shell
❯ HOMEBREW_GITHUB_API_TOKEN=<token_without_gist_scope> brew gist-logs logrotate
Error: Your GitHub API token likely doesn't have the `gist` scope.
Create a GitHub personal access token:
https://github.com/settings/tokens/new?scopes=gist&description=Homebrew
echo 'export HOMEBREW_GITHUB_API_TOKEN=your_token_here' >> ~/.zshrc
```
This commit is contained in:
Issy Long 2023-02-06 15:24:20 +01:00
parent 39e158fb93
commit 41b143deec
No known key found for this signature in database
GPG Key ID: 8247C390DADC67D4
2 changed files with 24 additions and 13 deletions

View File

@ -63,7 +63,15 @@ module Homebrew
else
"#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs"
end
begin
url = GitHub.create_gist(files, descr, private: args.private?)
rescue GitHub::API::HTTPNotFoundError
odie <<~EOS
Your GitHub API token likely doesn't have the `gist` scope.
#{GitHub.pat_blurb(GitHub::CREATE_GIST_SCOPES)}
EOS
end
url = GitHub.create_issue(f.tap, "#{f.name} failed to build on #{MacOS.full_version}", url) if args.new_issue?

View File

@ -5,7 +5,18 @@ require "tempfile"
require "utils/shell"
require "utils/formatter"
# A module that interfaces with GitHub, code like PAT scopes, credential handling and API errors.
module GitHub
def self.pat_blurb(scopes = ALL_SCOPES)
<<~EOS
Create a GitHub personal access token:
#{Formatter.url(
"https://github.com/settings/tokens/new?scopes=#{scopes.join(",")}&description=Homebrew",
)}
#{Utils::Shell.set_variable_in_profile("HOMEBREW_GITHUB_API_TOKEN", "your_token_here")}
EOS
end
API_URL = "https://api.github.com"
API_MAX_PAGES = 50
API_MAX_ITEMS = 5000
@ -14,14 +25,6 @@ module GitHub
CREATE_ISSUE_FORK_OR_PR_SCOPES = ["repo"].freeze
CREATE_WORKFLOW_SCOPES = ["workflow"].freeze
ALL_SCOPES = (CREATE_GIST_SCOPES + CREATE_ISSUE_FORK_OR_PR_SCOPES + CREATE_WORKFLOW_SCOPES).freeze
ALL_SCOPES_URL = Formatter.url(
"https://github.com/settings/tokens/new?scopes=#{ALL_SCOPES.join(",")}&description=Homebrew",
).freeze
CREATE_GITHUB_PAT_MESSAGE = <<~EOS
Create a GitHub personal access token:
#{ALL_SCOPES_URL}
#{Utils::Shell.set_variable_in_profile("HOMEBREW_GITHUB_API_TOKEN", "your_token_here")}
EOS
GITHUB_PERSONAL_ACCESS_TOKEN_REGEX = /^(?:[a-f0-9]{40}|gh[po]_\w{36,251})$/.freeze
# Helper functions to access the GitHub API.
@ -49,7 +52,7 @@ module GitHub
class RateLimitExceededError < Error
def initialize(reset, github_message)
@github_message = github_message
new_pat_message = ", or:\n#{CREATE_GITHUB_PAT_MESSAGE}" if API.credentials.blank?
new_pat_message = ", or:\n#{pat_blurb}" if API.credentials.blank?
super <<~EOS
GitHub API Error: #{github_message}
Try again in #{pretty_ratelimit_reset(reset)}#{new_pat_message}
@ -76,7 +79,7 @@ module GitHub
The GitHub credentials in the macOS keychain may be invalid.
Clear them with:
printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
#{CREATE_GITHUB_PAT_MESSAGE}
#{pat_blurb}
EOS
end
super message.freeze
@ -87,7 +90,7 @@ module GitHub
class MissingAuthenticationError < Error
def initialize
message = +"No GitHub credentials found in macOS Keychain or environment.\n"
message << CREATE_GITHUB_PAT_MESSAGE
message << pat_blurb
super message
end
end
@ -177,7 +180,7 @@ module GitHub
Your #{what} credentials do not have sufficient scope!
Scopes required: #{needed_scopes}
Scopes present: #{credentials_scopes}
#{CREATE_GITHUB_PAT_MESSAGE}
#{pat_blurb}
EOS
end