Support casks in brew audit.
This commit is contained in:
parent
97a7b02f8e
commit
24cef5c2ce
@ -51,7 +51,7 @@ module Cask
|
|||||||
casks = casks.map { |c| CaskLoader.load(c, config: Config.from_args(args)) }
|
casks = casks.map { |c| CaskLoader.load(c, config: Config.from_args(args)) }
|
||||||
casks = Cask.to_a if casks.empty?
|
casks = Cask.to_a if casks.empty?
|
||||||
|
|
||||||
self.class.audit_casks(
|
results = self.class.audit_casks(
|
||||||
*casks,
|
*casks,
|
||||||
download: args.download?,
|
download: args.download?,
|
||||||
appcast: args.appcast?,
|
appcast: args.appcast?,
|
||||||
@ -62,6 +62,13 @@ module Cask
|
|||||||
quarantine: args.quarantine?,
|
quarantine: args.quarantine?,
|
||||||
language: args.language,
|
language: args.language,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.class.print_annotations(results)
|
||||||
|
|
||||||
|
failed_casks = results.reject { |_, result| result[:errors].empty? }.map(&:first)
|
||||||
|
return if failed_casks.empty?
|
||||||
|
|
||||||
|
raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.audit_casks(
|
def self.audit_casks(
|
||||||
@ -92,11 +99,16 @@ module Cask
|
|||||||
|
|
||||||
require "cask/auditor"
|
require "cask/auditor"
|
||||||
|
|
||||||
failed_casks = casks.reject do |cask|
|
casks.map do |cask|
|
||||||
odebug "Auditing Cask #{cask}"
|
odebug "Auditing Cask #{cask}"
|
||||||
result = Auditor.audit(cask, **options)
|
[cask, Auditor.audit(cask, **options)]
|
||||||
|
end.to_h
|
||||||
|
end
|
||||||
|
|
||||||
if ENV["GITHUB_ACTIONS"]
|
def self.print_annotations(results)
|
||||||
|
return unless ENV["GITHUB_ACTIONS"]
|
||||||
|
|
||||||
|
results.each do |cask, result|
|
||||||
cask_path = cask.sourcefile_path
|
cask_path = cask.sourcefile_path
|
||||||
annotations = (result[:warnings].map { |w| [:warning, w] } + result[:errors].map { |e| [:error, e] })
|
annotations = (result[:warnings].map { |w| [:warning, w] } + result[:errors].map { |e| [:error, e] })
|
||||||
.map { |type, message| GitHub::Actions::Annotation.new(type, message, file: cask_path) }
|
.map { |type, message| GitHub::Actions::Annotation.new(type, message, file: cask_path) }
|
||||||
@ -105,13 +117,6 @@ module Cask
|
|||||||
puts annotation if annotation.relevant?
|
puts annotation if annotation.relevant?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
result[:errors].empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
return if failed_casks.empty?
|
|
||||||
|
|
||||||
raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -28,12 +28,12 @@ module Homebrew
|
|||||||
def audit_args
|
def audit_args
|
||||||
Homebrew::CLI::Parser.new do
|
Homebrew::CLI::Parser.new do
|
||||||
usage_banner <<~EOS
|
usage_banner <<~EOS
|
||||||
`audit` [<options>] [<formula>]
|
`audit` [<options>] [<formula>|<cask>]
|
||||||
|
|
||||||
Check <formula> for Homebrew coding style violations. This should be run before
|
Check <formula> for Homebrew coding style violations. This should be run before
|
||||||
submitting a new formula. If no <formula> are provided, check all locally
|
submitting a new formula or cask. If no <formula>|<cask> are provided, check all
|
||||||
available formulae and skip style checks. Will exit with a non-zero status if any
|
locally available formulae and casks and skip style checks. Will exit with a
|
||||||
errors are found.
|
non-zero status if any errors are found.
|
||||||
EOS
|
EOS
|
||||||
switch "--strict",
|
switch "--strict",
|
||||||
description: "Run additional, stricter style checks."
|
description: "Run additional, stricter style checks."
|
||||||
@ -41,8 +41,8 @@ module Homebrew
|
|||||||
description: "Run additional, slower style checks that navigate the Git repository."
|
description: "Run additional, slower style checks that navigate the Git repository."
|
||||||
switch "--online",
|
switch "--online",
|
||||||
description: "Run additional, slower style checks that require a network connection."
|
description: "Run additional, slower style checks that require a network connection."
|
||||||
switch "--new-formula",
|
switch "--new", "--new-formula", "--new-cask",
|
||||||
description: "Run various additional style checks to determine if a new formula is eligible "\
|
description: "Run various additional style checks to determine if a new formula or cask is eligible "\
|
||||||
"for Homebrew. This should be used when creating new formula and implies "\
|
"for Homebrew. This should be used when creating new formula and implies "\
|
||||||
"`--strict` and `--online`."
|
"`--strict` and `--online`."
|
||||||
flag "--tap=",
|
flag "--tap=",
|
||||||
@ -72,6 +72,18 @@ module Homebrew
|
|||||||
description: "Specify a comma-separated <cops> list to skip checking for violations of the listed "\
|
description: "Specify a comma-separated <cops> list to skip checking for violations of the listed "\
|
||||||
"RuboCop cops."
|
"RuboCop cops."
|
||||||
|
|
||||||
|
switch "--formula", "--formulae",
|
||||||
|
description: "Treat all named arguments as formulae."
|
||||||
|
switch "--cask", "--casks",
|
||||||
|
description: "Treat all named arguments as casks."
|
||||||
|
|
||||||
|
switch "--[no-]appcast",
|
||||||
|
description: "Audit the appcast"
|
||||||
|
switch "--token-conflicts",
|
||||||
|
description: "Audit for token conflicts"
|
||||||
|
|
||||||
|
conflicts "--formula", "--cask"
|
||||||
|
|
||||||
conflicts "--only", "--except"
|
conflicts "--only", "--except"
|
||||||
conflicts "--only-cops", "--except-cops", "--strict"
|
conflicts "--only-cops", "--except-cops", "--strict"
|
||||||
conflicts "--only-cops", "--except-cops", "--only"
|
conflicts "--only-cops", "--except-cops", "--only"
|
||||||
@ -81,6 +93,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def audit
|
def audit
|
||||||
args = audit_args.parse
|
args = audit_args.parse
|
||||||
|
|
||||||
@ -97,30 +110,34 @@ module Homebrew
|
|||||||
git = args.git?
|
git = args.git?
|
||||||
skip_style = args.skip_style? || args.no_named? || args.tap
|
skip_style = args.skip_style? || args.no_named? || args.tap
|
||||||
|
|
||||||
|
only = :formula if args.formula? && !args.cask?
|
||||||
|
only = :cask if args.cask? && !args.formula?
|
||||||
|
|
||||||
ENV.activate_extensions!
|
ENV.activate_extensions!
|
||||||
ENV.setup_build_environment
|
ENV.setup_build_environment
|
||||||
|
|
||||||
audit_formulae = if args.tap
|
audit_formulae, audit_casks = if args.tap
|
||||||
Tap.fetch(args.tap).formula_names.map { |name| Formula[name] }
|
Tap.fetch(args.tap).formula_names.map { |name| Formula[name] }
|
||||||
elsif args.no_named?
|
elsif args.no_named?
|
||||||
Formula
|
[Formula, Cask::Cask.to_a]
|
||||||
else
|
else
|
||||||
args.named.to_resolved_formulae
|
args.named.to_formulae_and_casks(only: only)
|
||||||
|
.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) }
|
||||||
end
|
end
|
||||||
style_files = args.named.to_formulae_paths unless skip_style
|
style_files = args.named.to_paths unless skip_style
|
||||||
|
|
||||||
only_cops = args.only_cops
|
only_cops = args.only_cops
|
||||||
except_cops = args.except_cops
|
except_cops = args.except_cops
|
||||||
options = { fix: args.fix?, debug: args.debug?, verbose: args.verbose? }
|
style_options = { fix: args.fix?, debug: args.debug?, verbose: args.verbose? }
|
||||||
|
|
||||||
if only_cops
|
if only_cops
|
||||||
options[:only_cops] = only_cops
|
style_options[:only_cops] = only_cops
|
||||||
elsif args.new_formula?
|
elsif args.new_formula?
|
||||||
nil
|
nil
|
||||||
elsif except_cops
|
elsif except_cops
|
||||||
options[:except_cops] = except_cops
|
style_options[:except_cops] = except_cops
|
||||||
elsif !strict
|
elsif !strict
|
||||||
options[:except_cops] = [:FormulaAuditStrict]
|
style_options[:except_cops] = [:FormulaAuditStrict]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run tap audits first
|
# Run tap audits first
|
||||||
@ -129,7 +146,7 @@ module Homebrew
|
|||||||
Tap.each do |tap|
|
Tap.each do |tap|
|
||||||
next if args.tap && tap != args.tap
|
next if args.tap && tap != args.tap
|
||||||
|
|
||||||
ta = TapAuditor.new tap, strict: args.strict?
|
ta = TapAuditor.new(tap, strict: args.strict?)
|
||||||
ta.audit
|
ta.audit
|
||||||
|
|
||||||
next if ta.problems.blank?
|
next if ta.problems.blank?
|
||||||
@ -142,7 +159,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Check style in a single batch run up front for performance
|
# Check style in a single batch run up front for performance
|
||||||
style_offenses = Style.check_style_json(style_files, options) if style_files
|
style_offenses = Style.check_style_json(style_files, style_options) if style_files
|
||||||
# load licenses
|
# load licenses
|
||||||
spdx_license_data = SPDX.license_data
|
spdx_license_data = SPDX.license_data
|
||||||
spdx_exception_data = SPDX.exception_data
|
spdx_exception_data = SPDX.exception_data
|
||||||
@ -159,19 +176,19 @@ module Homebrew
|
|||||||
spdx_license_data: spdx_license_data,
|
spdx_license_data: spdx_license_data,
|
||||||
spdx_exception_data: spdx_exception_data,
|
spdx_exception_data: spdx_exception_data,
|
||||||
tap_audit_exceptions: f.tap.audit_exceptions,
|
tap_audit_exceptions: f.tap.audit_exceptions,
|
||||||
}
|
style_offenses: style_offenses ? style_offenses.for_path(f.path) : nil,
|
||||||
options[:style_offenses] = style_offenses.for_path(f.path) if style_offenses
|
display_cop_names: args.display_cop_names?,
|
||||||
options[:display_cop_names] = args.display_cop_names?
|
build_stable: args.build_stable?,
|
||||||
options[:build_stable] = args.build_stable?
|
}.compact
|
||||||
|
|
||||||
fa = FormulaAuditor.new(f, options)
|
fa = FormulaAuditor.new(f, **options)
|
||||||
fa.audit
|
fa.audit
|
||||||
next if fa.problems.empty? && fa.new_formula_problems.empty?
|
next if fa.problems.empty? && fa.new_formula_problems.empty?
|
||||||
|
|
||||||
formula_count += 1
|
formula_count += 1
|
||||||
problem_count += fa.problems.size
|
problem_count += fa.problems.size
|
||||||
problem_lines = format_problem_lines(fa.problems)
|
problem_lines = format_problem_lines(fa.problems)
|
||||||
corrected_problem_count = options[:style_offenses].count(&:corrected?) if options[:style_offenses]
|
corrected_problem_count = options[:style_offenses]&.count(&:corrected?)
|
||||||
new_formula_problem_lines = format_problem_lines(fa.new_formula_problems)
|
new_formula_problem_lines = format_problem_lines(fa.new_formula_problems)
|
||||||
if args.display_filename?
|
if args.display_filename?
|
||||||
puts problem_lines.map { |s| "#{f.path}: #{s}" }
|
puts problem_lines.map { |s| "#{f.path}: #{s}" }
|
||||||
@ -189,24 +206,49 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
new_formula_problem_count += new_formula_problem_lines.size
|
casks_results = if audit_casks.empty?
|
||||||
puts new_formula_problem_lines.map { |s| " #{s}" }
|
[]
|
||||||
|
else
|
||||||
|
require "cask/cmd/audit"
|
||||||
|
|
||||||
total_problems_count = problem_count + new_formula_problem_count + tap_problem_count
|
Cask::Cmd::Audit.audit_casks(
|
||||||
|
*audit_casks,
|
||||||
|
download: nil,
|
||||||
|
appcast: args.appcast?,
|
||||||
|
online: args.online?,
|
||||||
|
strict: args.strict?,
|
||||||
|
new_cask: args.new_cask?,
|
||||||
|
token_conflicts: args.token_conflicts?,
|
||||||
|
quarantine: nil,
|
||||||
|
language: nil,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
failed_casks = casks_results.reject { |_, result| result[:errors].empty? }
|
||||||
|
|
||||||
|
cask_count = failed_casks.count
|
||||||
|
|
||||||
|
cask_problem_count = failed_casks.sum { |_, result| result[:warnings].count + result[:errors].count }
|
||||||
|
new_formula_problem_count += new_formula_problem_lines.count
|
||||||
|
total_problems_count = problem_count + new_formula_problem_count + cask_problem_count + tap_problem_count
|
||||||
return unless total_problems_count.positive?
|
return unless total_problems_count.positive?
|
||||||
|
|
||||||
problem_plural = "#{total_problems_count} #{"problem".pluralize(total_problems_count)}"
|
puts new_formula_problem_lines.map { |s| " #{s}" }
|
||||||
formula_plural = "#{formula_count} #{"formula".pluralize(formula_count)}"
|
|
||||||
tap_plural = "#{tap_count} #{"tap".pluralize(tap_count)}"
|
errors_summary = "#{total_problems_count} #{"problem".pluralize(total_problems_count)}"
|
||||||
corrected_problem_plural = "#{corrected_problem_count} #{"problem".pluralize(corrected_problem_count)}"
|
|
||||||
errors_summary = if tap_count.zero?
|
error_sources = []
|
||||||
"#{problem_plural} in #{formula_plural} detected"
|
error_sources << "#{formula_count} #{"formula".pluralize(formula_count)}" if formula_count.positive?
|
||||||
elsif formula_count.zero?
|
error_sources << "#{cask_count} #{"cask".pluralize(cask_count)}" if cask_count.positive?
|
||||||
"#{problem_plural} in #{tap_plural} detected"
|
error_sources << "#{tap_count} #{"tap".pluralize(tap_count)}" if tap_count.positive?
|
||||||
else
|
|
||||||
"#{problem_plural} in #{formula_plural} and #{tap_plural} detected"
|
errors_summary += " in #{error_sources.to_sentence}" if error_sources.any?
|
||||||
|
|
||||||
|
errors_summary += " detected"
|
||||||
|
|
||||||
|
if corrected_problem_count.positive?
|
||||||
|
errors_summary += ", #{corrected_problem_count} #{"problem".pluralize(corrected_problem_count)} corrected"
|
||||||
end
|
end
|
||||||
errors_summary += ", #{corrected_problem_plural} corrected" if corrected_problem_count.positive?
|
|
||||||
|
|
||||||
ofail errors_summary
|
ofail errors_summary
|
||||||
end
|
end
|
||||||
|
|||||||
@ -736,12 +736,12 @@ Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homeb
|
|||||||
|
|
||||||
## DEVELOPER COMMANDS
|
## DEVELOPER COMMANDS
|
||||||
|
|
||||||
### `audit` [*`options`*] [*`formula`*]
|
### `audit` [*`options`*] [*`formula`*|*`cask`*]
|
||||||
|
|
||||||
Check *`formula`* for Homebrew coding style violations. This should be run before
|
Check *`formula`* for Homebrew coding style violations. This should be run before
|
||||||
submitting a new formula. If no *`formula`* are provided, check all locally
|
submitting a new formula or cask. If no *`formula`*|*`cask`* are provided, check all
|
||||||
available formulae and skip style checks. Will exit with a non-zero status if any
|
locally available formulae and casks and skip style checks. Will exit with a
|
||||||
errors are found.
|
non-zero status if any errors are found.
|
||||||
|
|
||||||
* `--strict`:
|
* `--strict`:
|
||||||
Run additional, stricter style checks.
|
Run additional, stricter style checks.
|
||||||
@ -749,8 +749,8 @@ errors are found.
|
|||||||
Run additional, slower style checks that navigate the Git repository.
|
Run additional, slower style checks that navigate the Git repository.
|
||||||
* `--online`:
|
* `--online`:
|
||||||
Run additional, slower style checks that require a network connection.
|
Run additional, slower style checks that require a network connection.
|
||||||
* `--new-formula`:
|
* `--new`:
|
||||||
Run various additional style checks to determine if a new formula is eligible for Homebrew. This should be used when creating new formula and implies `--strict` and `--online`.
|
Run various additional style checks to determine if a new formula or cask is eligible for Homebrew. This should be used when creating new formula and implies `--strict` and `--online`.
|
||||||
* `--tap`:
|
* `--tap`:
|
||||||
Check the formulae within the given tap, specified as *`user`*`/`*`repo`*.
|
Check the formulae within the given tap, specified as *`user`*`/`*`repo`*.
|
||||||
* `--fix`:
|
* `--fix`:
|
||||||
@ -771,6 +771,14 @@ errors are found.
|
|||||||
Specify a comma-separated *`cops`* list to check for violations of only the listed RuboCop cops.
|
Specify a comma-separated *`cops`* list to check for violations of only the listed RuboCop cops.
|
||||||
* `--except-cops`:
|
* `--except-cops`:
|
||||||
Specify a comma-separated *`cops`* list to skip checking for violations of the listed RuboCop cops.
|
Specify a comma-separated *`cops`* list to skip checking for violations of the listed RuboCop cops.
|
||||||
|
* `--formula`:
|
||||||
|
Treat all named arguments as formulae.
|
||||||
|
* `--cask`:
|
||||||
|
Treat all named arguments as casks.
|
||||||
|
* `--[no-]appcast`:
|
||||||
|
Audit the appcast
|
||||||
|
* `--token-conflicts`:
|
||||||
|
Audit for token conflicts
|
||||||
|
|
||||||
### `bottle` [*`options`*] *`formula`*
|
### `bottle` [*`options`*] *`formula`*
|
||||||
|
|
||||||
|
|||||||
@ -997,8 +997,8 @@ Print the version numbers of Homebrew, Homebrew/homebrew\-core and Homebrew/home
|
|||||||
.
|
.
|
||||||
.SH "DEVELOPER COMMANDS"
|
.SH "DEVELOPER COMMANDS"
|
||||||
.
|
.
|
||||||
.SS "\fBaudit\fR [\fIoptions\fR] [\fIformula\fR]"
|
.SS "\fBaudit\fR [\fIoptions\fR] [\fIformula\fR|\fIcask\fR]"
|
||||||
Check \fIformula\fR for Homebrew coding style violations\. This should be run before submitting a new formula\. If no \fIformula\fR are provided, check all locally available formulae and skip style checks\. Will exit with a non\-zero status if any errors are found\.
|
Check \fIformula\fR for Homebrew coding style violations\. This should be run before submitting a new formula or cask\. If no \fIformula\fR|\fIcask\fR are provided, check all locally available formulae and casks and skip style checks\. Will exit with a non\-zero status if any errors are found\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-strict\fR
|
\fB\-\-strict\fR
|
||||||
@ -1013,8 +1013,8 @@ Run additional, slower style checks that navigate the Git repository\.
|
|||||||
Run additional, slower style checks that require a network connection\.
|
Run additional, slower style checks that require a network connection\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-new\-formula\fR
|
\fB\-\-new\fR
|
||||||
Run various additional style checks to determine if a new formula is eligible for Homebrew\. This should be used when creating new formula and implies \fB\-\-strict\fR and \fB\-\-online\fR\.
|
Run various additional style checks to determine if a new formula or cask is eligible for Homebrew\. This should be used when creating new formula and implies \fB\-\-strict\fR and \fB\-\-online\fR\.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-tap\fR
|
\fB\-\-tap\fR
|
||||||
@ -1056,6 +1056,22 @@ Specify a comma\-separated \fIcops\fR list to check for violations of only the l
|
|||||||
\fB\-\-except\-cops\fR
|
\fB\-\-except\-cops\fR
|
||||||
Specify a comma\-separated \fIcops\fR list to skip checking for violations of the listed RuboCop cops\.
|
Specify a comma\-separated \fIcops\fR list to skip checking for violations of the listed RuboCop cops\.
|
||||||
.
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-formula\fR
|
||||||
|
Treat all named arguments as formulae\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-cask\fR
|
||||||
|
Treat all named arguments as casks\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-[no\-]appcast\fR
|
||||||
|
Audit the appcast
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-token\-conflicts\fR
|
||||||
|
Audit for token conflicts
|
||||||
|
.
|
||||||
.SS "\fBbottle\fR [\fIoptions\fR] \fIformula\fR"
|
.SS "\fBbottle\fR [\fIoptions\fR] \fIformula\fR"
|
||||||
Generate a bottle (binary package) from a formula that was installed with \fB\-\-build\-bottle\fR\. If the formula specifies a rebuild version, it will be incremented in the generated DSL\. Passing \fB\-\-keep\-old\fR will attempt to keep it at its original value, while \fB\-\-no\-rebuild\fR will remove it\.
|
Generate a bottle (binary package) from a formula that was installed with \fB\-\-build\-bottle\fR\. If the formula specifies a rebuild version, it will be incremented in the generated DSL\. Passing \fB\-\-keep\-old\fR will attempt to keep it at its original value, while \fB\-\-no\-rebuild\fR will remove it\.
|
||||||
.
|
.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user