From 41b143deecbaaeb8dae6970aabfa51d2cab2e8cf Mon Sep 17 00:00:00 2001 From: Issy Long Date: Mon, 6 Feb 2023 15:24:20 +0100 Subject: [PATCH] cmd/gist-logs: On 404, the PAT probably needs more permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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= brew gist-logs -p logrotate Error: Not Found ``` After: ```shell ❯ HOMEBREW_GITHUB_API_TOKEN= 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 ``` --- Library/Homebrew/cmd/gist-logs.rb | 10 +++++++++- Library/Homebrew/utils/github/api.rb | 27 +++++++++++++++------------ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb index 81a76f7036..1931724d35 100644 --- a/Library/Homebrew/cmd/gist-logs.rb +++ b/Library/Homebrew/cmd/gist-logs.rb @@ -63,7 +63,15 @@ module Homebrew else "#{f.name} (#{f.full_name}) on #{OS_VERSION} - Homebrew build logs" 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? diff --git a/Library/Homebrew/utils/github/api.rb b/Library/Homebrew/utils/github/api.rb index 2855ca4eea..c174c12314 100644 --- a/Library/Homebrew/utils/github/api.rb +++ b/Library/Homebrew/utils/github/api.rb @@ -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