Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audit: Make --display-failures-only the default for Casks #15105

Merged
merged 10 commits into from Apr 7, 2023
10 changes: 5 additions & 5 deletions .github/workflows/tests.yml
Expand Up @@ -151,7 +151,7 @@ jobs:
run: brew readall --aliases homebrew/core

- name: Run brew audit --skip-style on homebrew/core
run: brew audit --skip-style --except=version --display-failures-only --tap=homebrew/core
run: brew audit --skip-style --except=version --tap=homebrew/core

cask-audit:
name: cask audit
Expand Down Expand Up @@ -187,10 +187,10 @@ jobs:

- name: Run brew audit --skip-style on casks
run: |
brew audit --skip-style --except=version --display-failures-only --tap=homebrew/cask
brew audit --skip-style --except=version --display-failures-only --tap=homebrew/cask-drivers
brew audit --skip-style --except=version --display-failures-only --tap=homebrew/cask-fonts
brew audit --skip-style --except=version --display-failures-only --tap=homebrew/cask-versions
brew audit --skip-style --except=version --tap=homebrew/cask
brew audit --skip-style --except=version --tap=homebrew/cask-drivers
brew audit --skip-style --except=version --tap=homebrew/cask-fonts
brew audit --skip-style --except=version --tap=homebrew/cask-versions

vendored-gems:
name: vendored gems
Expand Down
98 changes: 32 additions & 66 deletions Library/Homebrew/cask/audit.rb
Expand Up @@ -71,66 +71,38 @@ def errors
@errors ||= []
end

def warnings
@warnings ||= []
end

sig { returns(T::Boolean) }
def errors?
errors.any?
end

sig { returns(T::Boolean) }
def warnings?
warnings.any?
end

sig { returns(T::Boolean) }
def success?
!(errors? || warnings?)
!errors?
end

sig { params(message: T.nilable(String), location: T.nilable(String)).void }
def add_error(message, location: nil)
errors << ({ message: message, location: location })
end
sig { params(message: T.nilable(String), location: T.nilable(String), strict_only: T::Boolean).void }
def add_error(message, location: nil, strict_only: false)
# Only raise non-critical audits if the user specified `--strict`.
return if strict_only && !@strict

sig { params(message: T.nilable(String), location: T.nilable(String)).void }
def add_warning(message, location: nil)
if strict?
add_error message, location: location
else
warnings << ({ message: message, location: location })
end
errors << ({ message: message, location: location })
end

def result
if errors?
Formatter.error("failed")
elsif warnings?
Formatter.warning("warning")
else
Formatter.success("passed")
end
Formatter.error("failed") if errors?
end

sig { params(include_passed: T::Boolean, include_warnings: T::Boolean).returns(T.nilable(String)) }
def summary(include_passed: false, include_warnings: true)
return if success? && !include_passed
return if warnings? && !errors? && !include_warnings
sig { returns(T.nilable(String)) }
def summary
return if success?

summary = ["audit for #{cask}: #{result}"]

errors.each do |error|
summary << " #{Formatter.error("-")} #{error[:message]}"
end

if include_warnings
warnings.each do |warning|
summary << " #{Formatter.warning("-")} #{warning[:message]}"
end
end

summary.join("\n")
end

Expand Down Expand Up @@ -220,7 +192,7 @@ def audit_description
# increases the maintenance burden.
return if cask.tap == "homebrew/cask-fonts"

add_warning "Cask should have a description. Please add a `desc` stanza." if cask.desc.blank?
add_error("Cask should have a description. Please add a `desc` stanza.", strict_only: true) if cask.desc.blank?
end

sig { void }
Expand Down Expand Up @@ -408,8 +380,10 @@ def audit_token_conflicts
return unless token_conflicts?
return unless core_formula_names.include?(cask.token)

add_warning "possible duplicate, cask token conflicts with Homebrew core formula: " \
"#{Formatter.url(core_formula_url)}"
add_error(
"possible duplicate, cask token conflicts with Homebrew core formula: #{Formatter.url(core_formula_url)}",
strict_only: true,
)
end

sig { void }
Expand Down Expand Up @@ -443,18 +417,19 @@ def audit_token_bad_words
add_error "cask token contains version designation '#{match_data[:designation]}'"
end

add_warning "cask token mentions launcher" if token.end_with? "launcher"
add_error("cask token mentions launcher", strict_only: true) if token.end_with? "launcher"

add_warning "cask token mentions desktop" if token.end_with? "desktop"
add_error("cask token mentions desktop", strict_only: true) if token.end_with? "desktop"

add_warning "cask token mentions platform" if token.end_with? "mac", "osx", "macos"
add_error("cask token mentions platform", strict_only: true) if token.end_with? "mac", "osx", "macos"

add_warning "cask token mentions architecture" if token.end_with? "x86", "32_bit", "x86_64", "64_bit"
add_error("cask token mentions architecture", strict_only: true) if token.end_with? "x86", "32_bit", "x86_64",
"64_bit"

frameworks = %w[cocoa qt gtk wx java]
return if frameworks.include?(token) || !token.end_with?(*frameworks)

add_warning "cask token mentions framework"
add_error("cask token mentions framework", strict_only: true)
end

sig { void }
Expand All @@ -474,7 +449,10 @@ def audit_livecheck_unneeded_long_version
return if cask.url.to_s.include? cask.version.csv.second
return if cask.version.csv.third.present? && cask.url.to_s.include?(cask.version.csv.third)

add_warning "Download does not require additional version components. Use `&:short_version` in the livecheck"
add_error(
"Download does not require additional version components. Use `&:short_version` in the livecheck",
strict_only: true,
)
end

sig { void }
Expand Down Expand Up @@ -518,15 +496,15 @@ def audit_signing
"#{message} fix the signature of their app."
end

add_warning message
add_error(message, strict_only: true)
when Artifact::Pkg
path = downloaded_path
next unless path.exist?

result = system_command("pkgutil", args: ["--check-signature", path], print_stderr: false)

unless result.success?
add_warning <<~EOS
add_error(<<~EOS, strict_only: true)
Signature verification failed:
#{result.merged_output}
macOS on ARM requires applications to be signed.
Expand All @@ -538,7 +516,7 @@ def audit_signing
result = system_command("stapler", args: ["validate", path], print_stderr: false)
next if result.success?

add_warning <<~EOS
add_error(<<~EOS, strict_only: true)
Signature verification failed:
#{result.merged_output}
macOS on ARM requires applications to be signed.
Expand Down Expand Up @@ -663,16 +641,10 @@ def audit_github_repository_archived

metadata = SharedAudits.github_repo_data(user, repo)
return if metadata.nil?

return unless metadata["archived"]

message = "GitHub repo is archived"

if cask.discontinued?
add_warning message
else
add_error message
end
# Discontinued casks shouldn't show up as errors.
add_error("GitHub repo is archived", strict_only: !cask.discontinued?)
issyl0 marked this conversation as resolved.
Show resolved Hide resolved
end

sig { void }
Expand All @@ -684,16 +656,10 @@ def audit_gitlab_repository_archived

metadata = SharedAudits.gitlab_repo_data(user, repo)
return if metadata.nil?

return unless metadata["archived"]

message = "GitLab repo is archived"

if cask.discontinued?
add_warning message
else
add_error message
end
# Discontinued casks shouldn't show up as errors.
add_error("GitLab repo is archived") unless cask.discontinued?
end

sig { void }
Expand Down
30 changes: 4 additions & 26 deletions Library/Homebrew/cask/auditor.rb
Expand Up @@ -25,8 +25,6 @@ def initialize(
quarantine: nil,
any_named_args: nil,
language: nil,
display_passes: nil,
display_failures_only: nil,
only: [],
except: []
)
Expand All @@ -40,16 +38,13 @@ def initialize(
@audit_token_conflicts = audit_token_conflicts
@any_named_args = any_named_args
@language = language
@display_passes = display_passes
@display_failures_only = display_failures_only
@only = only
@except = except
end

LANGUAGE_BLOCK_LIMIT = 10

def audit
warnings = Set.new
errors = Set.new

if !language && language_blocks
Expand All @@ -63,23 +58,19 @@ def audit

sample_languages.each_key do |l|
audit = audit_languages(l)
summary = audit.summary(include_passed: output_passed?, include_warnings: output_warnings?)
if summary.present? && output_summary?(audit)
if audit.summary.present? && output_summary?(audit)
ohai "Auditing language: #{l.map { |lang| "'#{lang}'" }.to_sentence}" if output_summary?
puts summary
puts audit.summary
end
warnings += audit.warnings
errors += audit.errors
end
else
audit = audit_cask_instance(cask)
summary = audit.summary(include_passed: output_passed?, include_warnings: output_warnings?)
puts summary if summary.present? && output_summary?(audit)
warnings += audit.warnings
puts audit.summary if audit.summary.present? && output_summary?(audit)
errors += audit.errors
end

{ warnings: warnings, errors: errors }
errors
end

private
Expand All @@ -92,19 +83,6 @@ def output_summary?(audit = nil)
audit.errors?
end

def output_passed?
return false if @display_failures_only.present?
return true if @display_passes.present?

false
end

def output_warnings?
return false if @display_failures_only.present?

true
end

def audit_languages(languages)
original_config = cask.config
localized_config = original_config.merge(Config.new(explicit: { languages: languages }))
Expand Down
32 changes: 12 additions & 20 deletions Library/Homebrew/cask/cmd/audit.rb
Expand Up @@ -30,8 +30,6 @@ def self.parser
description: "Run various additional style checks to determine if a new cask is eligible " \
"for Homebrew. This should be used when creating new casks and implies " \
"`--strict` and `--online`"
switch "--display-failures-only",
description: "Only display casks that fail the audit. This is the default for formulae."
end
end

Expand All @@ -49,19 +47,17 @@ def run

results = self.class.audit_casks(
*casks,
download: args.download?,
online: args.online?,
strict: args.strict?,
signing: args.signing?,
new_cask: args.new_cask?,
token_conflicts: args.token_conflicts?,
quarantine: args.quarantine?,
any_named_args: any_named_args,
language: args.language,
display_passes: args.verbose? || args.named.count == 1,
display_failures_only: args.display_failures_only?,
only: [],
except: [],
download: args.download?,
online: args.online?,
strict: args.strict?,
signing: args.signing?,
new_cask: args.new_cask?,
token_conflicts: args.token_conflicts?,
quarantine: args.quarantine?,
any_named_args: any_named_args,
language: args.language,
only: [],
except: [],
)

failed_casks = results.reject { |_, result| result[:errors].empty? }.map(&:first)
Expand All @@ -81,8 +77,6 @@ def self.audit_casks(
quarantine:,
any_named_args:,
language:,
display_passes:,
display_failures_only:,
only:,
except:
)
Expand All @@ -96,8 +90,6 @@ def self.audit_casks(
quarantine: quarantine,
language: language,
any_named_args: any_named_args,
display_passes: display_passes,
display_failures_only: display_failures_only,
only: only,
except: except,
}.compact
Expand All @@ -110,7 +102,7 @@ def self.audit_casks(

casks.to_h do |cask|
odebug "Auditing Cask #{cask}"
[cask.sourcefile_path, Auditor.audit(cask, **options)]
[cask.sourcefile_path, { errors: Auditor.audit(cask, **options), warnings: [] }]
end
end
end
Expand Down