diff --git a/Library/Homebrew/attestation.rb b/Library/Homebrew/attestation.rb index eb8c9729d1..e8d641814c 100644 --- a/Library/Homebrew/attestation.rb +++ b/Library/Homebrew/attestation.rb @@ -33,6 +33,11 @@ module Homebrew # @api private BACKFILL_CUTOFF = T.let(DateTime.new(2024, 3, 14).freeze, DateTime) + # Raised when the attestation was not found. + # + # @api private + class MissingAttestationError < RuntimeError; end + # Raised when attestation verification fails. # # @api private @@ -150,6 +155,8 @@ module Homebrew raise GhAuthInvalid, "invalid credentials" end + raise MissingAttestationError, "attestation not found: #{e}" if e.stderr.include?("HTTP 404: Not Found") + raise InvalidAttestationError, "attestation verification failed: #{e}" end @@ -212,7 +219,7 @@ module Homebrew # attestations currently do not include reusable workflow state by default. attestation = check_attestation bottle, HOMEBREW_CORE_REPO return attestation - rescue InvalidAttestationError + rescue MissingAttestationError odebug "falling back on backfilled attestation for #{bottle}" # Our backfilled attestation is a little unique: the subject is not just the bottle diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index ee9d16981e..e73c05b52e 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -1310,7 +1310,7 @@ on_request: installed_on_request?, options:) gh auth login EOS - rescue Homebrew::Attestation::InvalidAttestationError => e + rescue Homebrew::Attestation::MissingAttestationError, Homebrew::Attestation::InvalidAttestationError => e raise CannotInstallFormulaError, <<~EOS The bottle for #{formula.name} has an invalid build provenance attestation. diff --git a/Library/Homebrew/test/attestation_spec.rb b/Library/Homebrew/test/attestation_spec.rb index 312a1ba787..73c7b2d27e 100644 --- a/Library/Homebrew/test/attestation_spec.rb +++ b/Library/Homebrew/test/attestation_spec.rb @@ -251,14 +251,14 @@ RSpec.describe Homebrew::Attestation do described_class.check_core_attestation fake_bottle end - it "calls gh with args for backfill when homebrew-core fails" do + it "calls gh with args for backfill when homebrew-core attestation is missing" do expect(described_class).to receive(:system_command!) .with(fake_gh, args: ["attestation", "verify", cached_download, "--repo", described_class::HOMEBREW_CORE_REPO, "--format", "json"], env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds], print_stderr: false, chdir: HOMEBREW_TEMP) .once - .and_raise(described_class::InvalidAttestationError) + .and_raise(described_class::MissingAttestationError) expect(described_class).to receive(:system_command!) .with(fake_gh, args: ["attestation", "verify", cached_download, "--repo", @@ -277,7 +277,7 @@ RSpec.describe Homebrew::Attestation do env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds], print_stderr: false, chdir: HOMEBREW_TEMP) .once - .and_raise(described_class::InvalidAttestationError) + .and_raise(described_class::MissingAttestationError) expect(described_class).to receive(:system_command!) .with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",