Merge pull request #4278 from commitay/audit-sourceforge-appcast
cask audit: check for sourceforge appcast
This commit is contained in:
commit
bb7ec947e4
@ -34,7 +34,7 @@ module Hbc
|
|||||||
check_single_pre_postflight
|
check_single_pre_postflight
|
||||||
check_single_uninstall_zap
|
check_single_uninstall_zap
|
||||||
check_untrusted_pkg
|
check_untrusted_pkg
|
||||||
check_github_releases_appcast
|
check_hosting_with_appcast
|
||||||
check_latest_with_appcast
|
check_latest_with_appcast
|
||||||
check_stanza_requires_uninstall
|
check_stanza_requires_uninstall
|
||||||
self
|
self
|
||||||
@ -246,11 +246,23 @@ module Hbc
|
|||||||
add_warning "Casks with an appcast should not use version :latest"
|
add_warning "Casks with an appcast should not use version :latest"
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_github_releases_appcast
|
def check_hosting_with_appcast
|
||||||
return if cask.appcast
|
return if cask.appcast
|
||||||
|
check_github_releases_appcast
|
||||||
|
check_sourceforge_appcast
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_github_releases_appcast
|
||||||
return unless cask.url.to_s =~ %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
return unless cask.url.to_s =~ %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
||||||
|
|
||||||
add_warning "Cask uses GitHub releases, please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
add_warning "Download uses GitHub releases, please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_sourceforge_appcast
|
||||||
|
return if cask.version.latest?
|
||||||
|
return unless cask.url.to_s =~ %r{sourceforge.net/(\S+)}
|
||||||
|
|
||||||
|
add_warning "Download is hosted on SourceForge, please add an appcast. See https://github.com/Homebrew/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_url
|
def check_url
|
||||||
|
|||||||
@ -94,190 +94,190 @@ describe Hbc::Audit, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "pkg allow_untrusted checks" do
|
describe "pkg allow_untrusted checks" do
|
||||||
let(:error_msg) { "allow_untrusted is not permitted in official Homebrew-Cask taps" }
|
let(:warning_msg) { "allow_untrusted is not permitted in official Homebrew-Cask taps" }
|
||||||
|
|
||||||
context "when the Cask has no pkg stanza" do
|
context "when the Cask has no pkg stanza" do
|
||||||
let(:cask_token) { "basic-cask" }
|
let(:cask_token) { "basic-cask" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask does not have allow_untrusted" do
|
context "when the Cask does not have allow_untrusted" do
|
||||||
let(:cask_token) { "with-uninstall-pkgutil" }
|
let(:cask_token) { "with-uninstall-pkgutil" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has allow_untrusted" do
|
context "when the Cask has allow_untrusted" do
|
||||||
let(:cask_token) { "with-allow-untrusted" }
|
let(:cask_token) { "with-allow-untrusted" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "when the Cask stanza requires uninstall" do
|
describe "when the Cask stanza requires uninstall" do
|
||||||
let(:error_msg) { "installer and pkg stanzas require an uninstall stanza" }
|
let(:warning_msg) { "installer and pkg stanzas require an uninstall stanza" }
|
||||||
|
|
||||||
context "when the Cask does not require an uninstall" do
|
context "when the Cask does not require an uninstall" do
|
||||||
let(:cask_token) { "basic-cask" }
|
let(:cask_token) { "basic-cask" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the pkg Cask has an uninstall" do
|
context "when the pkg Cask has an uninstall" do
|
||||||
let(:cask_token) { "with-uninstall-pkgutil" }
|
let(:cask_token) { "with-uninstall-pkgutil" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the installer Cask has an uninstall" do
|
context "when the installer Cask has an uninstall" do
|
||||||
let(:cask_token) { "installer-with-uninstall" }
|
let(:cask_token) { "installer-with-uninstall" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the installer Cask does not have an uninstall" do
|
context "when the installer Cask does not have an uninstall" do
|
||||||
let(:cask_token) { "with-installer-manual" }
|
let(:cask_token) { "with-installer-manual" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the pkg Cask does not have an uninstall" do
|
context "when the pkg Cask does not have an uninstall" do
|
||||||
let(:cask_token) { "pkg-without-uninstall" }
|
let(:cask_token) { "pkg-without-uninstall" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "preflight stanza checks" do
|
describe "preflight stanza checks" do
|
||||||
let(:error_msg) { "only a single preflight stanza is allowed" }
|
let(:warning_msg) { "only a single preflight stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no preflight stanza" do
|
context "when the Cask has no preflight stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one preflight stanza" do
|
context "when the Cask has only one preflight stanza" do
|
||||||
let(:cask_token) { "with-preflight" }
|
let(:cask_token) { "with-preflight" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple preflight stanzas" do
|
context "when the Cask has multiple preflight stanzas" do
|
||||||
let(:cask_token) { "with-preflight-multi" }
|
let(:cask_token) { "with-preflight-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uninstall_postflight stanza checks" do
|
describe "uninstall_postflight stanza checks" do
|
||||||
let(:error_msg) { "only a single postflight stanza is allowed" }
|
let(:warning_msg) { "only a single postflight stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no postflight stanza" do
|
context "when the Cask has no postflight stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one postflight stanza" do
|
context "when the Cask has only one postflight stanza" do
|
||||||
let(:cask_token) { "with-postflight" }
|
let(:cask_token) { "with-postflight" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple postflight stanzas" do
|
context "when the Cask has multiple postflight stanzas" do
|
||||||
let(:cask_token) { "with-postflight-multi" }
|
let(:cask_token) { "with-postflight-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uninstall stanza checks" do
|
describe "uninstall stanza checks" do
|
||||||
let(:error_msg) { "only a single uninstall stanza is allowed" }
|
let(:warning_msg) { "only a single uninstall stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no uninstall stanza" do
|
context "when the Cask has no uninstall stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one uninstall stanza" do
|
context "when the Cask has only one uninstall stanza" do
|
||||||
let(:cask_token) { "with-uninstall-rmdir" }
|
let(:cask_token) { "with-uninstall-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple uninstall stanzas" do
|
context "when the Cask has multiple uninstall stanzas" do
|
||||||
let(:cask_token) { "with-uninstall-multi" }
|
let(:cask_token) { "with-uninstall-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uninstall_preflight stanza checks" do
|
describe "uninstall_preflight stanza checks" do
|
||||||
let(:error_msg) { "only a single uninstall_preflight stanza is allowed" }
|
let(:warning_msg) { "only a single uninstall_preflight stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no uninstall_preflight stanza" do
|
context "when the Cask has no uninstall_preflight stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one uninstall_preflight stanza" do
|
context "when the Cask has only one uninstall_preflight stanza" do
|
||||||
let(:cask_token) { "with-uninstall-preflight" }
|
let(:cask_token) { "with-uninstall-preflight" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple uninstall_preflight stanzas" do
|
context "when the Cask has multiple uninstall_preflight stanzas" do
|
||||||
let(:cask_token) { "with-uninstall-preflight-multi" }
|
let(:cask_token) { "with-uninstall-preflight-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "uninstall_postflight stanza checks" do
|
describe "uninstall_postflight stanza checks" do
|
||||||
let(:error_msg) { "only a single uninstall_postflight stanza is allowed" }
|
let(:warning_msg) { "only a single uninstall_postflight stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no uninstall_postflight stanza" do
|
context "when the Cask has no uninstall_postflight stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one uninstall_postflight stanza" do
|
context "when the Cask has only one uninstall_postflight stanza" do
|
||||||
let(:cask_token) { "with-uninstall-postflight" }
|
let(:cask_token) { "with-uninstall-postflight" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple uninstall_postflight stanzas" do
|
context "when the Cask has multiple uninstall_postflight stanzas" do
|
||||||
let(:cask_token) { "with-uninstall-postflight-multi" }
|
let(:cask_token) { "with-uninstall-postflight-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "zap stanza checks" do
|
describe "zap stanza checks" do
|
||||||
let(:error_msg) { "only a single zap stanza is allowed" }
|
let(:warning_msg) { "only a single zap stanza is allowed" }
|
||||||
|
|
||||||
context "when the Cask has no zap stanza" do
|
context "when the Cask has no zap stanza" do
|
||||||
let(:cask_token) { "with-uninstall-rmdir" }
|
let(:cask_token) { "with-uninstall-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has only one zap stanza" do
|
context "when the Cask has only one zap stanza" do
|
||||||
let(:cask_token) { "with-zap-rmdir" }
|
let(:cask_token) { "with-zap-rmdir" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask has multiple zap stanzas" do
|
context "when the Cask has multiple zap stanzas" do
|
||||||
let(:cask_token) { "with-zap-multi" }
|
let(:cask_token) { "with-zap-multi" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -439,46 +439,68 @@ describe Hbc::Audit, :cask do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "GitHub releases appcast check" do
|
describe "GitHub releases appcast check" do
|
||||||
let(:error_msg) { /Cask uses GitHub releases/ }
|
let(:appcast_warning) { /Download uses GitHub releases/ }
|
||||||
|
|
||||||
context "when the Cask does not use GitHub releases" do
|
context "when the download does not use GitHub releases" do
|
||||||
let(:cask_token) { "basic-cask" }
|
let(:cask_token) { "basic-cask" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(appcast_warning) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask uses GitHub releases and has an appcast" do
|
context "when the download uses GitHub releases and has an appcast" do
|
||||||
let(:cask_token) { "github-with-appcast" }
|
let(:cask_token) { "github-with-appcast" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(appcast_warning) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask uses GitHub releases and does not have an appcast" do
|
context "when the download uses GitHub releases and does not have an appcast" do
|
||||||
let(:cask_token) { "github-without-appcast" }
|
let(:cask_token) { "github-without-appcast" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(appcast_warning) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "SourceForge appcast check" do
|
||||||
|
let(:appcast_warning) { /Download is hosted on SourceForge/ }
|
||||||
|
|
||||||
|
context "when the download is not hosted on SourceForge" do
|
||||||
|
let(:cask_token) { "basic-cask" }
|
||||||
|
|
||||||
|
it { is_expected.not_to warn_with(appcast_warning) }
|
||||||
|
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) }
|
||||||
|
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) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "latest with appcast checks" do
|
describe "latest with appcast checks" do
|
||||||
let(:error_msg) { "Casks with an appcast should not use version :latest" }
|
let(:warning_msg) { "Casks with an appcast should not use version :latest" }
|
||||||
|
|
||||||
context "when the Cask is :latest and does not have an appcast" do
|
context "when the Cask is :latest and does not have an appcast" do
|
||||||
let(:cask_token) { "version-latest" }
|
let(:cask_token) { "version-latest" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask is versioned and has an appcast" do
|
context "when the Cask is versioned and has an appcast" do
|
||||||
let(:cask_token) { "with-appcast" }
|
let(:cask_token) { "with-appcast" }
|
||||||
|
|
||||||
it { is_expected.not_to warn_with(error_msg) }
|
it { is_expected.not_to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the Cask is :latest and has an appcast" do
|
context "when the Cask is :latest and has an appcast" do
|
||||||
let(:cask_token) { "latest-with-appcast" }
|
let(:cask_token) { "latest-with-appcast" }
|
||||||
|
|
||||||
it { is_expected.to warn_with(error_msg) }
|
it { is_expected.to warn_with(warning_msg) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
cask 'sourceforge-with-appcast' do
|
||||||
|
version '1.2.3'
|
||||||
|
|
||||||
|
url 'https://downloads.sourceforge.net/something/Something-1.2.3.dmg'
|
||||||
|
appcast 'https://sourceforge.net/projects/something/rss',
|
||||||
|
checkpoint: '407fb59baa4b9eb7651d9243b89c30b7481590947ef78bd5a4c24f5810f56531'
|
||||||
|
homepage 'https://sourceforge.net/projects/something/'
|
||||||
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user