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 else
"#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs" "#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs"
end end
url = GitHub.create_gist(files, descr, private: args.private?)
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? 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/shell"
require "utils/formatter" require "utils/formatter"
# A module that interfaces with GitHub, code like PAT scopes, credential handling and API errors.
module GitHub 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_URL = "https://api.github.com"
API_MAX_PAGES = 50 API_MAX_PAGES = 50
API_MAX_ITEMS = 5000 API_MAX_ITEMS = 5000
@ -14,14 +25,6 @@ module GitHub
CREATE_ISSUE_FORK_OR_PR_SCOPES = ["repo"].freeze CREATE_ISSUE_FORK_OR_PR_SCOPES = ["repo"].freeze
CREATE_WORKFLOW_SCOPES = ["workflow"].freeze CREATE_WORKFLOW_SCOPES = ["workflow"].freeze
ALL_SCOPES = (CREATE_GIST_SCOPES + CREATE_ISSUE_FORK_OR_PR_SCOPES + CREATE_WORKFLOW_SCOPES).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 GITHUB_PERSONAL_ACCESS_TOKEN_REGEX = /^(?:[a-f0-9]{40}|gh[po]_\w{36,251})$/.freeze
# Helper functions to access the GitHub API. # Helper functions to access the GitHub API.
@ -49,7 +52,7 @@ module GitHub
class RateLimitExceededError < Error class RateLimitExceededError < Error
def initialize(reset, github_message) def initialize(reset, github_message)
@github_message = 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 super <<~EOS
GitHub API Error: #{github_message} GitHub API Error: #{github_message}
Try again in #{pretty_ratelimit_reset(reset)}#{new_pat_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. The GitHub credentials in the macOS keychain may be invalid.
Clear them with: Clear them with:
printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
#{CREATE_GITHUB_PAT_MESSAGE} #{pat_blurb}
EOS EOS
end end
super message.freeze super message.freeze
@ -87,7 +90,7 @@ module GitHub
class MissingAuthenticationError < Error class MissingAuthenticationError < Error
def initialize def initialize
message = +"No GitHub credentials found in macOS Keychain or environment.\n" message = +"No GitHub credentials found in macOS Keychain or environment.\n"
message << CREATE_GITHUB_PAT_MESSAGE message << pat_blurb
super message super message
end end
end end
@ -177,7 +180,7 @@ module GitHub
Your #{what} credentials do not have sufficient scope! Your #{what} credentials do not have sufficient scope!
Scopes required: #{needed_scopes} Scopes required: #{needed_scopes}
Scopes present: #{credentials_scopes} Scopes present: #{credentials_scopes}
#{CREATE_GITHUB_PAT_MESSAGE} #{pat_blurb}
EOS EOS
end end