Merge pull request #8719 from reitermarkus/cask-audit-errors
Refactor `cask audit` warnings.
This commit is contained in:
commit
7589a350cc
@ -30,8 +30,8 @@ module Cask
|
||||
appcast = online if appcast.nil?
|
||||
download = online if download.nil?
|
||||
|
||||
# `strict` implies `token_conflicts`
|
||||
token_conflicts = strict if token_conflicts.nil?
|
||||
# `new_cask` implies `token_conflicts`
|
||||
token_conflicts = new_cask if token_conflicts.nil?
|
||||
|
||||
@cask = cask
|
||||
@appcast = appcast
|
||||
@ -91,7 +91,11 @@ module Cask
|
||||
end
|
||||
|
||||
def add_warning(message)
|
||||
warnings << message
|
||||
if strict?
|
||||
add_error message
|
||||
else
|
||||
warnings << message
|
||||
end
|
||||
end
|
||||
|
||||
def errors?
|
||||
@ -143,7 +147,7 @@ module Cask
|
||||
|
||||
return unless cask.artifacts.any? { |k| k.is_a?(Artifact::Pkg) && k.stanza_options.key?(:allow_untrusted) }
|
||||
|
||||
add_warning "allow_untrusted is not permitted in official Homebrew Cask taps"
|
||||
add_error "allow_untrusted is not permitted in official Homebrew Cask taps"
|
||||
end
|
||||
|
||||
def check_stanza_requires_uninstall
|
||||
@ -152,14 +156,14 @@ module Cask
|
||||
return if cask.artifacts.none? { |k| k.is_a?(Artifact::Pkg) || k.is_a?(Artifact::Installer) }
|
||||
return if cask.artifacts.any? { |k| k.is_a?(Artifact::Uninstall) }
|
||||
|
||||
add_warning "installer and pkg stanzas require an uninstall stanza"
|
||||
add_error "installer and pkg stanzas require an uninstall stanza"
|
||||
end
|
||||
|
||||
def check_single_pre_postflight
|
||||
odebug "Auditing preflight and postflight stanzas"
|
||||
|
||||
if cask.artifacts.count { |k| k.is_a?(Artifact::PreflightBlock) && k.directives.key?(:preflight) } > 1
|
||||
add_warning "only a single preflight stanza is allowed"
|
||||
add_error "only a single preflight stanza is allowed"
|
||||
end
|
||||
|
||||
count = cask.artifacts.count do |k|
|
||||
@ -168,14 +172,14 @@ module Cask
|
||||
end
|
||||
return unless count > 1
|
||||
|
||||
add_warning "only a single postflight stanza is allowed"
|
||||
add_error "only a single postflight stanza is allowed"
|
||||
end
|
||||
|
||||
def check_single_uninstall_zap
|
||||
odebug "Auditing single uninstall_* and zap stanzas"
|
||||
|
||||
if cask.artifacts.count { |k| k.is_a?(Artifact::Uninstall) } > 1
|
||||
add_warning "only a single uninstall stanza is allowed"
|
||||
add_error "only a single uninstall stanza is allowed"
|
||||
end
|
||||
|
||||
count = cask.artifacts.count do |k|
|
||||
@ -183,18 +187,18 @@ module Cask
|
||||
k.directives.key?(:uninstall_preflight)
|
||||
end
|
||||
|
||||
add_warning "only a single uninstall_preflight stanza is allowed" if count > 1
|
||||
add_error "only a single uninstall_preflight stanza is allowed" if count > 1
|
||||
|
||||
count = cask.artifacts.count do |k|
|
||||
k.is_a?(Artifact::PostflightBlock) &&
|
||||
k.directives.key?(:uninstall_postflight)
|
||||
end
|
||||
|
||||
add_warning "only a single uninstall_postflight stanza is allowed" if count > 1
|
||||
add_error "only a single uninstall_postflight stanza is allowed" if count > 1
|
||||
|
||||
return unless cask.artifacts.count { |k| k.is_a?(Artifact::Zap) } > 1
|
||||
|
||||
add_warning "only a single zap stanza is allowed"
|
||||
add_error "only a single zap stanza is allowed"
|
||||
end
|
||||
|
||||
def check_required_stanzas
|
||||
@ -267,14 +271,14 @@ module Cask
|
||||
return unless cask.version.latest?
|
||||
return unless cask.appcast
|
||||
|
||||
add_warning "Casks with an appcast should not use version :latest"
|
||||
add_error "Casks with an appcast should not use version :latest"
|
||||
end
|
||||
|
||||
def check_latest_with_auto_updates
|
||||
return unless cask.version.latest?
|
||||
return unless cask.auto_updates
|
||||
|
||||
add_warning "Casks with `version :latest` should not use `auto_updates`"
|
||||
add_error "Casks with `version :latest` should not use `auto_updates`"
|
||||
end
|
||||
|
||||
def check_hosting_with_appcast
|
||||
@ -286,21 +290,19 @@ module Cask
|
||||
when %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
||||
return if cask.version.latest?
|
||||
|
||||
add_warning "Download uses GitHub releases, #{add_appcast}"
|
||||
add_error "Download uses GitHub releases, #{add_appcast}"
|
||||
when %r{sourceforge.net/(\S+)}
|
||||
return if cask.version.latest?
|
||||
|
||||
add_warning "Download is hosted on SourceForge, #{add_appcast}"
|
||||
add_error "Download is hosted on SourceForge, #{add_appcast}"
|
||||
when %r{dl.devmate.com/(\S+)}
|
||||
add_warning "Download is hosted on DevMate, #{add_appcast}"
|
||||
add_error "Download is hosted on DevMate, #{add_appcast}"
|
||||
when %r{rink.hockeyapp.net/(\S+)}
|
||||
add_warning "Download is hosted on HockeyApp, #{add_appcast}"
|
||||
add_error "Download is hosted on HockeyApp, #{add_appcast}"
|
||||
end
|
||||
end
|
||||
|
||||
def check_desc
|
||||
return unless new_cask?
|
||||
|
||||
return if cask.desc.present?
|
||||
|
||||
add_warning "Cask should have a description. Please add a `desc` stanza."
|
||||
@ -315,9 +317,9 @@ module Cask
|
||||
def check_download_url_format
|
||||
odebug "Auditing URL format"
|
||||
if bad_sourceforge_url?
|
||||
add_warning "SourceForge URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
|
||||
add_error "SourceForge URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
|
||||
elsif bad_osdn_url?
|
||||
add_warning "OSDN URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
|
||||
add_error "OSDN URL format incorrect. See https://github.com/Homebrew/homebrew-cask/blob/HEAD/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls"
|
||||
end
|
||||
end
|
||||
|
||||
@ -363,42 +365,33 @@ module Cask
|
||||
end
|
||||
|
||||
def check_token_valid
|
||||
return unless strict?
|
||||
|
||||
add_warning "cask token is not lowercase" if cask.token.downcase!
|
||||
|
||||
add_warning "cask token contains non-ascii characters" unless cask.token.ascii_only?
|
||||
|
||||
add_warning "cask token + should be replaced by -plus-" if cask.token.include? "+"
|
||||
|
||||
add_warning "cask token @ should be replaced by -at-" if cask.token.include? "@"
|
||||
|
||||
add_warning "cask token whitespace should be replaced by hyphens" if cask.token.include? " "
|
||||
|
||||
add_warning "cask token underscores should be replaced by hyphens" if cask.token.include? "_"
|
||||
add_error "cask token contains non-ascii characters" unless cask.token.ascii_only?
|
||||
add_error "cask token + should be replaced by -plus-" if cask.token.include? "+"
|
||||
add_error "cask token whitespace should be replaced by hyphens" if cask.token.include? " "
|
||||
add_error "cask token @ should be replaced by -at-" if cask.token.include? "@"
|
||||
add_error "cask token underscores should be replaced by hyphens" if cask.token.include? "_"
|
||||
add_error "cask token should not contain double hyphens" if cask.token.include? "--"
|
||||
|
||||
if cask.token.match?(/[^a-z0-9\-]/)
|
||||
add_warning "cask token should only contain alphanumeric characters and hyphens"
|
||||
add_error "cask token should only contain lowercase alphanumeric characters and hyphens"
|
||||
end
|
||||
|
||||
add_warning "cask token should not contain double hyphens" if cask.token.include? "--"
|
||||
return unless cask.token.start_with?("-") || cask.token.end_with?("-")
|
||||
|
||||
return unless cask.token.end_with?("-") || cask.token.start_with?("-")
|
||||
|
||||
add_warning "cask token should not have leading or trailing hyphens"
|
||||
add_error "cask token should not have leading or trailing hyphens"
|
||||
end
|
||||
|
||||
def check_token_bad_words
|
||||
return unless strict?
|
||||
return unless new_cask?
|
||||
|
||||
token = cask.token
|
||||
|
||||
add_warning "cask token contains .app" if token.end_with? ".app"
|
||||
add_error "cask token contains .app" if token.end_with? ".app"
|
||||
|
||||
if /-(?<designation>alpha|beta|rc|release-candidate)$/ =~ cask.token &&
|
||||
cask.tap&.official? &&
|
||||
cask.tap != "homebrew/cask-versions"
|
||||
add_warning "cask token contains version designation '#{designation}'"
|
||||
add_error "cask token contains version designation '#{designation}'"
|
||||
end
|
||||
|
||||
add_warning "cask token mentions launcher" if token.end_with? "launcher"
|
||||
@ -433,7 +426,7 @@ module Cask
|
||||
downloaded_path = download.perform
|
||||
Verify.all(cask, downloaded_path)
|
||||
rescue => e
|
||||
add_error "download not possible: #{e.message}"
|
||||
add_error "download not possible: #{e}"
|
||||
end
|
||||
|
||||
def check_appcast_contains_version
|
||||
@ -458,7 +451,7 @@ module Cask
|
||||
end
|
||||
return if appcast_contents.include? adjusted_version_stanza
|
||||
|
||||
add_warning "appcast at URL '#{appcast_stanza}' does not contain"\
|
||||
add_error "appcast at URL '#{appcast_stanza}' does not contain"\
|
||||
" the version number '#{adjusted_version_stanza}':\n#{appcast_contents}"
|
||||
end
|
||||
|
||||
|
||||
@ -59,8 +59,6 @@ module Cask
|
||||
odebug "Auditing Cask #{cask}"
|
||||
result = Auditor.audit(cask, **options)
|
||||
|
||||
next true if result[:warnings].empty? && result[:errors].empty?
|
||||
|
||||
if ENV["GITHUB_ACTIONS"]
|
||||
cask_path = cask.sourcefile_path
|
||||
annotations = (result[:warnings].map { |w| [:warning, w] } + result[:errors].map { |e| [:error, e] })
|
||||
@ -71,7 +69,7 @@ module Cask
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
result[:errors].empty?
|
||||
end
|
||||
|
||||
return if failed_casks.empty?
|
||||
|
||||
@ -17,15 +17,15 @@ describe Cask::Audit, :cask do
|
||||
end
|
||||
end
|
||||
|
||||
matcher :fail_with do |error_msg|
|
||||
matcher :fail_with do |message|
|
||||
match do |audit|
|
||||
include_msg?(audit.errors, error_msg)
|
||||
include_msg?(audit.errors, message)
|
||||
end
|
||||
end
|
||||
|
||||
matcher :warn_with do |warning_msg|
|
||||
matcher :warn_with do |message|
|
||||
match do |audit|
|
||||
include_msg?(audit.warnings, warning_msg)
|
||||
include_msg?(audit.warnings, message)
|
||||
end
|
||||
end
|
||||
|
||||
@ -53,6 +53,10 @@ describe Cask::Audit, :cask do
|
||||
it "implies `strict`" do
|
||||
expect(audit).to be_strict
|
||||
end
|
||||
|
||||
it "implies `token_conflicts`" do
|
||||
expect(audit.token_conflicts?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context "when `online` is specified" do
|
||||
@ -66,14 +70,6 @@ describe Cask::Audit, :cask do
|
||||
expect(audit.download).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "when `strict` is specified" do
|
||||
let(:strict) { true }
|
||||
|
||||
it "implies `token_conflicts`" do
|
||||
expect(audit.token_conflicts?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#result" do
|
||||
@ -152,78 +148,87 @@ describe Cask::Audit, :cask do
|
||||
context "when cask token is not lowercase" do
|
||||
let(:cask_token) { "Upper-Case" }
|
||||
|
||||
it "warns about lowercase" do
|
||||
expect(subject).to warn_with(/token is not lowercase/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/lowercase/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token is not ascii" do
|
||||
let(:cask_token) { "ascii⌘" }
|
||||
|
||||
it "warns about ascii" do
|
||||
expect(subject).to warn_with(/contains non-ascii characters/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/contains non-ascii characters/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has +" do
|
||||
let(:cask_token) { "app++" }
|
||||
|
||||
it "warns about +" do
|
||||
expect(subject).to warn_with(/\+ should be replaced by -plus-/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/\+ should be replaced by -plus-/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has @" do
|
||||
let(:cask_token) { "app@stuff" }
|
||||
|
||||
it "warns about +" do
|
||||
expect(subject).to warn_with(/@ should be replaced by -at-/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/@ should be replaced by -at-/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has whitespace" do
|
||||
let(:cask_token) { "app stuff" }
|
||||
|
||||
it "warns about whitespace" do
|
||||
expect(subject).to warn_with(/whitespace should be replaced by hyphens/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/whitespace should be replaced by hyphens/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has underscores" do
|
||||
let(:cask_token) { "app_stuff" }
|
||||
|
||||
it "warns about underscores" do
|
||||
expect(subject).to warn_with(/underscores should be replaced by hyphens/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/underscores should be replaced by hyphens/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has non-alphanumeric characters" do
|
||||
let(:cask_token) { "app(stuff)" }
|
||||
|
||||
it "warns about non-alphanumeric characters" do
|
||||
expect(subject).to warn_with(/should only contain alphanumeric characters and hyphens/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/alphanumeric characters and hyphens/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has double hyphens" do
|
||||
let(:cask_token) { "app--stuff" }
|
||||
|
||||
it "warns about double hyphens" do
|
||||
expect(subject).to warn_with(/should not contain double hyphens/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/should not contain double hyphens/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has leading hyphens" do
|
||||
let(:cask_token) { "-app" }
|
||||
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/should not have leading or trailing hyphens/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token has trailing hyphens" do
|
||||
let(:cask_token) { "app-" }
|
||||
|
||||
it "warns about trailing hyphens" do
|
||||
expect(subject).to warn_with(/should not have leading or trailing hyphens/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/should not have leading or trailing hyphens/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "token bad words" do
|
||||
let(:strict) { true }
|
||||
let(:new_cask) { true }
|
||||
let(:online) { false }
|
||||
let(:cask) do
|
||||
tmp_cask cask_token.to_s, <<~RUBY
|
||||
cask '#{cask_token}' do
|
||||
@ -231,6 +236,7 @@ describe Cask::Audit, :cask do
|
||||
sha256 '8dd95daa037ac02455435446ec7bc737b34567afe9156af7d20b2a83805c1d8a'
|
||||
url "https://brew.sh/"
|
||||
name 'Audit'
|
||||
desc 'Cask for testing tokens'
|
||||
homepage 'https://brew.sh/'
|
||||
app 'Audit.app'
|
||||
end
|
||||
@ -240,72 +246,72 @@ describe Cask::Audit, :cask do
|
||||
context "when cask token contains .app" do
|
||||
let(:cask_token) { "token.app" }
|
||||
|
||||
it "warns about .app" do
|
||||
expect(subject).to warn_with(/token contains .app/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/token contains .app/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains version designation" do
|
||||
let(:cask_token) { "token-beta" }
|
||||
|
||||
it "warns about version in token if the cask is from an official tap" do
|
||||
it "fails if the cask is from an official tap" do
|
||||
allow(cask).to receive(:tap).and_return(Tap.fetch("homebrew/cask"))
|
||||
|
||||
expect(subject).to warn_with(/token contains version designation/)
|
||||
expect(subject).to fail_with(/token contains version designation/)
|
||||
end
|
||||
|
||||
it "does not warn about version in token if the cask is from the `cask-versions` tap" do
|
||||
it "does not fail if the cask is from the `cask-versions` tap" do
|
||||
allow(cask).to receive(:tap).and_return(Tap.fetch("homebrew/cask-versions"))
|
||||
|
||||
expect(subject).not_to warn_with(/token contains version designation/)
|
||||
expect(subject).to pass
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains launcher" do
|
||||
let(:cask_token) { "token-launcher" }
|
||||
|
||||
it "warns about launcher in token" do
|
||||
expect(subject).to warn_with(/token mentions launcher/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/token mentions launcher/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains desktop" do
|
||||
let(:cask_token) { "token-desktop" }
|
||||
|
||||
it "warns about desktop in token" do
|
||||
expect(subject).to warn_with(/token mentions desktop/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/token mentions desktop/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains platform" do
|
||||
let(:cask_token) { "token-osx" }
|
||||
|
||||
it "warns about platform in token" do
|
||||
expect(subject).to warn_with(/token mentions platform/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/token mentions platform/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains architecture" do
|
||||
let(:cask_token) { "token-x86" }
|
||||
|
||||
it "warns about architecture in token" do
|
||||
expect(subject).to warn_with(/token mentions architecture/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/token mentions architecture/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token contains framework" do
|
||||
let(:cask_token) { "token-java" }
|
||||
|
||||
it "warns about framework in token" do
|
||||
expect(subject).to warn_with(/cask token mentions framework/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/cask token mentions framework/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when cask token is framework" do
|
||||
let(:cask_token) { "java" }
|
||||
|
||||
it "does not warn about framework" do
|
||||
expect(subject).not_to warn_with(/token contains version/)
|
||||
it "does not fail" do
|
||||
expect(subject).to pass
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -358,206 +364,206 @@ describe Cask::Audit, :cask do
|
||||
end
|
||||
|
||||
describe "pkg allow_untrusted checks" do
|
||||
let(:warning_msg) { "allow_untrusted is not permitted in official Homebrew Cask taps" }
|
||||
let(:message) { "allow_untrusted is not permitted in official Homebrew Cask taps" }
|
||||
|
||||
context "when the Cask has no pkg stanza" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask does not have allow_untrusted" do
|
||||
let(:cask_token) { "with-uninstall-pkgutil" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has allow_untrusted" do
|
||||
let(:cask_token) { "with-allow-untrusted" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the Cask stanza requires uninstall" do
|
||||
let(:warning_msg) { "installer and pkg stanzas require an uninstall stanza" }
|
||||
let(:message) { "installer and pkg stanzas require an uninstall stanza" }
|
||||
|
||||
context "when the Cask does not require an uninstall" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the pkg Cask has an uninstall" do
|
||||
let(:cask_token) { "with-uninstall-pkgutil" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the installer Cask has an uninstall" do
|
||||
let(:cask_token) { "installer-with-uninstall" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the installer Cask does not have an uninstall" do
|
||||
let(:cask_token) { "with-installer-manual" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the pkg Cask does not have an uninstall" do
|
||||
let(:cask_token) { "pkg-without-uninstall" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "preflight stanza checks" do
|
||||
let(:warning_msg) { "only a single preflight stanza is allowed" }
|
||||
let(:message) { "only a single preflight stanza is allowed" }
|
||||
|
||||
context "when the Cask has no preflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one preflight stanza" do
|
||||
let(:cask_token) { "with-preflight" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple preflight stanzas" do
|
||||
let(:cask_token) { "with-preflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "uninstall_postflight stanza checks" do
|
||||
let(:warning_msg) { "only a single postflight stanza is allowed" }
|
||||
describe "postflight stanza checks" do
|
||||
let(:message) { "only a single postflight stanza is allowed" }
|
||||
|
||||
context "when the Cask has no postflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one postflight stanza" do
|
||||
let(:cask_token) { "with-postflight" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple postflight stanzas" do
|
||||
let(:cask_token) { "with-postflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "uninstall stanza checks" do
|
||||
let(:warning_msg) { "only a single uninstall stanza is allowed" }
|
||||
let(:message) { "only a single uninstall stanza is allowed" }
|
||||
|
||||
context "when the Cask has no uninstall stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one uninstall stanza" do
|
||||
let(:cask_token) { "with-uninstall-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple uninstall stanzas" do
|
||||
let(:cask_token) { "with-uninstall-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "uninstall_preflight stanza checks" do
|
||||
let(:warning_msg) { "only a single uninstall_preflight stanza is allowed" }
|
||||
let(:message) { "only a single uninstall_preflight stanza is allowed" }
|
||||
|
||||
context "when the Cask has no uninstall_preflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one uninstall_preflight stanza" do
|
||||
let(:cask_token) { "with-uninstall-preflight" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple uninstall_preflight stanzas" do
|
||||
let(:cask_token) { "with-uninstall-preflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "uninstall_postflight stanza checks" do
|
||||
let(:warning_msg) { "only a single uninstall_postflight stanza is allowed" }
|
||||
let(:message) { "only a single uninstall_postflight stanza is allowed" }
|
||||
|
||||
context "when the Cask has no uninstall_postflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one uninstall_postflight stanza" do
|
||||
let(:cask_token) { "with-uninstall-postflight" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple uninstall_postflight stanzas" do
|
||||
let(:cask_token) { "with-uninstall-postflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "zap stanza checks" do
|
||||
let(:warning_msg) { "only a single zap stanza is allowed" }
|
||||
let(:message) { "only a single zap stanza is allowed" }
|
||||
|
||||
context "when the Cask has no zap stanza" do
|
||||
let(:cask_token) { "with-uninstall-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has only one zap stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask has multiple zap stanzas" do
|
||||
let(:cask_token) { "with-zap-multi" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "version checks" do
|
||||
let(:error_msg) { "you should use version :latest instead of version 'latest'" }
|
||||
let(:message) { "you should use version :latest instead of version 'latest'" }
|
||||
|
||||
context "when version is 'latest'" do
|
||||
let(:cask_token) { "version-latest-string" }
|
||||
|
||||
it { is_expected.to fail_with(error_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when version is :latest" do
|
||||
let(:cask_token) { "version-latest-with-checksum" }
|
||||
|
||||
it { is_expected.not_to fail_with(error_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -582,93 +588,93 @@ describe Cask::Audit, :cask do
|
||||
end
|
||||
|
||||
describe "hosting with appcast checks" do
|
||||
let(:appcast_warning) { /please add an appcast/ }
|
||||
let(:message) { /please add an appcast/ }
|
||||
|
||||
context "when the download does not use hosting with an appcast" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download uses GitHub releases and has an appcast" do
|
||||
let(:cask_token) { "github-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download uses GitHub releases and does not have an appcast" do
|
||||
let(:cask_token) { "github-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on SourceForge and has an appcast" do
|
||||
let(:cask_token) { "sourceforge-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on SourceForge and does not have an appcast" do
|
||||
let(:cask_token) { "sourceforge-correct-url-format" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on DevMate and has an appcast" do
|
||||
let(:cask_token) { "devmate-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on DevMate and does not have an appcast" do
|
||||
let(:cask_token) { "devmate-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on HockeyApp and has an appcast" do
|
||||
let(:cask_token) { "hockeyapp-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(appcast_warning) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the download is hosted on HockeyApp and does not have an appcast" do
|
||||
let(:cask_token) { "hockeyapp-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(appcast_warning) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "latest with appcast checks" do
|
||||
let(:warning_msg) { "Casks with an appcast should not use version :latest" }
|
||||
let(:message) { "Casks with an appcast should not use version :latest" }
|
||||
|
||||
context "when the Cask is :latest and does not have an appcast" do
|
||||
let(:cask_token) { "version-latest" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask is versioned and has an appcast" do
|
||||
let(:cask_token) { "with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "when the Cask is :latest and has an appcast" do
|
||||
let(:cask_token) { "latest-with-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "denylist checks" do
|
||||
context "when the Cask isn't disallowed" do
|
||||
context "when the Cask is not on the denylist" do
|
||||
let(:cask_token) { "adobe-air" }
|
||||
|
||||
it { is_expected.to pass }
|
||||
end
|
||||
|
||||
context "when the Cask is disallowed" do
|
||||
context "when the Cask is on the denylist" do
|
||||
context "and it's in the official Homebrew tap" do
|
||||
let(:cask_token) { "adobe-illustrator" }
|
||||
|
||||
@ -684,64 +690,64 @@ describe Cask::Audit, :cask do
|
||||
end
|
||||
|
||||
describe "latest with auto_updates checks" do
|
||||
let(:warning_msg) { "Casks with `version :latest` should not use `auto_updates`" }
|
||||
let(:message) { "Casks with `version :latest` should not use `auto_updates`" }
|
||||
|
||||
context "when the Cask is :latest and does not have auto_updates" do
|
||||
let(:cask_token) { "version-latest" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.to pass }
|
||||
end
|
||||
|
||||
context "when the Cask is versioned and does not have auto_updates" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.to pass }
|
||||
end
|
||||
|
||||
context "when the Cask is versioned and has auto_updates" do
|
||||
let(:cask_token) { "auto-updates" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.to pass }
|
||||
end
|
||||
|
||||
context "when the Cask is :latest and has auto_updates" do
|
||||
let(:cask_token) { "latest-with-auto-updates" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "preferred download URL formats" do
|
||||
let(:warning_msg) { /URL format incorrect/ }
|
||||
let(:message) { /URL format incorrect/ }
|
||||
|
||||
context "with incorrect SourceForge URL format" do
|
||||
let(:cask_token) { "sourceforge-incorrect-url-format" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "with correct SourceForge URL format" do
|
||||
let(:cask_token) { "sourceforge-correct-url-format" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "with correct SourceForge URL format for version :latest" do
|
||||
let(:cask_token) { "sourceforge-version-latest-correct-url-format" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
|
||||
context "with incorrect OSDN URL format" do
|
||||
let(:cask_token) { "osdn-incorrect-url-format" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
it { is_expected.to fail_with(message) }
|
||||
end
|
||||
|
||||
context "with correct OSDN URL format" do
|
||||
let(:cask_token) { "osdn-correct-url-format" }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
it { is_expected.not_to fail_with(message) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -793,7 +799,7 @@ describe Cask::Audit, :cask do
|
||||
context "when cask token does not conflict with a core formula" do
|
||||
let(:formula_names) { %w[other-formula] }
|
||||
|
||||
it { is_expected.not_to warn_with(/possible duplicate/) }
|
||||
it { is_expected.to pass }
|
||||
end
|
||||
end
|
||||
|
||||
@ -802,27 +808,28 @@ describe Cask::Audit, :cask do
|
||||
let(:cask) { Cask::CaskLoader.load(cask_token) }
|
||||
let(:download_double) { instance_double(Cask::Download) }
|
||||
let(:verify) { class_double(Cask::Verify).as_stubbed_const }
|
||||
let(:error_msg) { "Download Failed" }
|
||||
let(:message) { "Download Failed" }
|
||||
|
||||
before do
|
||||
allow(audit).to receive(:download).and_return(download_double)
|
||||
allow(audit).to receive(:check_https_availability)
|
||||
end
|
||||
|
||||
it "when download and verification succeed it does not fail" do
|
||||
expect(download_double).to receive(:perform)
|
||||
expect(verify).to receive(:all)
|
||||
expect(subject).not_to fail_with(/#{error_msg}/)
|
||||
expect(subject).to pass
|
||||
end
|
||||
|
||||
it "when download fails it does not fail" do
|
||||
expect(download_double).to receive(:perform).and_raise(StandardError.new(error_msg))
|
||||
expect(subject).to fail_with(/#{error_msg}/)
|
||||
it "when download fails it fails" do
|
||||
expect(download_double).to receive(:perform).and_raise(StandardError.new(message))
|
||||
expect(subject).to fail_with(/#{message}/)
|
||||
end
|
||||
|
||||
it "when verification fails it does not fail" do
|
||||
it "when verification fails it fails" do
|
||||
expect(download_double).to receive(:perform)
|
||||
expect(verify).to receive(:all).and_raise(StandardError.new(error_msg))
|
||||
expect(subject).to fail_with(/#{error_msg}/)
|
||||
expect(verify).to receive(:all).and_raise(StandardError.new(message))
|
||||
expect(subject).to fail_with(/#{message}/)
|
||||
end
|
||||
end
|
||||
|
||||
@ -853,16 +860,16 @@ describe Cask::Audit, :cask do
|
||||
context "when `new_cask` is true" do
|
||||
let(:new_cask) { true }
|
||||
|
||||
it "warns" do
|
||||
expect(subject).to warn_with(/should have a description/)
|
||||
it "fails" do
|
||||
expect(subject).to fail_with(/should have a description/)
|
||||
end
|
||||
end
|
||||
|
||||
context "when `new_cask` is true" do
|
||||
context "when `new_cask` is false" do
|
||||
let(:new_cask) { false }
|
||||
|
||||
it "does not warn" do
|
||||
expect(subject).not_to warn_with(/should have a description/)
|
||||
it "warns" do
|
||||
expect(subject).to warn_with(/should have a description/)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -883,8 +890,8 @@ describe Cask::Audit, :cask do
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not warn" do
|
||||
expect(subject).not_to warn_with(/should have a description/)
|
||||
it "passes" do
|
||||
expect(subject).to pass
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -15,6 +15,8 @@ describe Cask::Cmd::Cat, :cask do
|
||||
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||
|
||||
url "https://brew.sh/TestCask.dmg"
|
||||
name "Basic Cask"
|
||||
desc "Cask for testing basic functionality"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
app "TestCask.app"
|
||||
|
||||
@ -3,7 +3,8 @@ cask "adobe-air" do
|
||||
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||
|
||||
url "https://brew.sh/TestCask.dmg"
|
||||
name "Adobe Air"
|
||||
name "Adobe AIR"
|
||||
desc "Cross-platform application runtime"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
app "TestCask.app"
|
||||
|
||||
@ -3,6 +3,8 @@ cask "auto-updates" do
|
||||
sha256 "5633c3a0f2e572cbf021507dec78c50998b398c343232bdfc7e26221d0a5db4d"
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyApp.zip"
|
||||
name "Auto-Updates"
|
||||
desc "Cask which auto-updates"
|
||||
homepage "https://brew.sh/MyFancyApp"
|
||||
|
||||
auto_updates true
|
||||
|
||||
@ -3,6 +3,8 @@ cask "basic-cask" do
|
||||
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||
|
||||
url "https://brew.sh/TestCask.dmg"
|
||||
name "Basic Cask"
|
||||
desc "Cask for testing basic functionality"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
app "TestCask.app"
|
||||
|
||||
@ -3,6 +3,8 @@ cask "latest-with-auto-updates" do
|
||||
sha256 :no_check
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||
name "Latest with Auto-Updates"
|
||||
desc "Unversioned cask which auto-updates"
|
||||
homepage "https://brew.sh/latest-with-auto-updates"
|
||||
|
||||
auto_updates true
|
||||
|
||||
@ -3,6 +3,8 @@ cask "pkg-without-uninstall" do
|
||||
sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip"
|
||||
name "PKG without Uninstall"
|
||||
desc "Cask with a package installer and no uninstall stanza"
|
||||
homepage "https://brew.sh/fancy-pkg"
|
||||
|
||||
pkg "Fancy.pkg"
|
||||
|
||||
@ -3,6 +3,8 @@ cask "version-latest" do
|
||||
sha256 :no_check
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/caffeines.zip"
|
||||
name "Version Latest"
|
||||
desc "Unversioned cask"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
app "Caffeine Mini.app"
|
||||
|
||||
@ -3,6 +3,8 @@ cask "with-binary" do
|
||||
sha256 "d5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2"
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/AppWithBinary.zip"
|
||||
name "With Binary"
|
||||
desc "Cask with a binary stanza"
|
||||
homepage "https://brew.sh/with-binary"
|
||||
|
||||
app "App.app"
|
||||
|
||||
@ -3,6 +3,8 @@ cask "with-installer-manual" do
|
||||
sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94"
|
||||
|
||||
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||
name "With Installer Manual"
|
||||
desc "Cask with a manual installer"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
installer manual: "Caffeine.app"
|
||||
|
||||
@ -4,6 +4,7 @@ cask "pharo" do
|
||||
|
||||
url "https://brew.sh/ThirdParty.dmg"
|
||||
name "Pharo"
|
||||
desc "Cask from a third-party tap"
|
||||
homepage "https://brew.sh/"
|
||||
|
||||
app "ThirdParty.app"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user