Check binary URL resources with RuboCop

- Migrate the existing binary URL audit to a RuboCop.
- Check resources as well as main URLs
- Also check for "macos" and "osx" in URLs
- Add whitelists for URLs and formulae
This commit is contained in:
Mike McQuaid 2019-09-02 10:50:49 +01:00
parent 9291fe583e
commit 4add1d1cb3
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
4 changed files with 48 additions and 90 deletions

View File

@ -920,18 +920,6 @@ module Homebrew
EOS EOS
end end
def audit_url_is_not_binary
return unless @core_tap
urls = @specs.map(&:url)
urls.each do |url|
if url =~ /darwin/i && (url =~ /x86_64/i || url =~ /amd64/i)
problem "#{url} looks like a binary package, not a source archive. The `core` tap is source-only."
end
end
end
def quote_dep(dep) def quote_dep(dep)
dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'" dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'"
end end

View File

@ -7,6 +7,28 @@ module RuboCop
module FormulaAudit module FormulaAudit
# This cop audits URLs and mirrors in Formulae. # This cop audits URLs and mirrors in Formulae.
class Urls < FormulaCop class Urls < FormulaCop
# These are formulae that, sadly, require an upstream binary to bootstrap.
BINARY_FORMULA_URLS_WHITELIST = %w[
crystal
fpc
ghc
ghc@8.2
go
go@1.9
go@1.10
go@1.11
haskell-stack
ldc
mlton
rust
].freeze
# specific rust-nightly temporarily acceptable until a newer version is released.
# DO NOT RE-ADD A NEWER RUST-NIGHTLY IN FUTURE.
BINARY_URLS_WHITELIST = %w[
https://static.rust-lang.org/dist/2019-08-24/rust-nightly-x86_64-apple-darwin.tar.xz
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node) def audit_formula(_node, _class_node, _parent_class_node, body_node)
urls = find_every_func_call_by_name(body_node, :url) urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror) mirrors = find_every_func_call_by_name(body_node, :mirror)
@ -202,6 +224,18 @@ module RuboCop
audit_urls(urls, maven_pattern) do |match, url| audit_urls(urls, maven_pattern) do |match, url|
problem "#{url} should be `https://search.maven.org/remotecontent?filepath=#{match[1]}`" problem "#{url} should be `https://search.maven.org/remotecontent?filepath=#{match[1]}`"
end end
return if formula_tap != "homebrew-core"
# Check for binary URLs
audit_urls(urls, /(darwin|macos|osx)/i) do |_, url|
next if url !~ /x86_64/i && url !~ /amd64/i
next if BINARY_FORMULA_URLS_WHITELIST.include?(@formula_name)
next if BINARY_URLS_WHITELIST.include?(url)
problem "#{url} looks like a binary package, not a source archive. " \
"Homebrew/homebrew-core is source-only."
end
end end
end end

View File

@ -530,84 +530,6 @@ module Homebrew
end end
end end
describe "#audit_url_is_not_binary" do
specify "it detects a url containing darwin and x86_64" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
RUBY
fa.audit_url_is_not_binary
expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end
specify "it detects a url containing darwin and amd64" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/example-darwin.amd64.tar.gz"
end
RUBY
fa.audit_url_is_not_binary
expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end
specify "it works on the devel spec" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"
devel do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY
fa.audit_url_is_not_binary
expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end
specify "it works on the head spec" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"
head do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY
fa.audit_url_is_not_binary
expect(fa.problems.first)
.to match("looks like a binary package, not a source archive. The `core` tap is source-only.")
end
specify "it ignores resource urls" do
fa = formula_auditor "foo", <<~RUBY, core_tap: true
class Foo < Formula
url "https://brew.sh/valid-1.0.tar.gz"
resource "binary_res" do
url "https://brew.sh/example-darwin.x86_64.tar.gz"
end
end
RUBY
fa.audit_url_is_not_binary
expect(fa.problems).to eq([])
end
end
describe "#audit_versioned_keg_only" do describe "#audit_versioned_keg_only" do
specify "it warns when a versioned formula is not `keg_only`" do specify "it warns when a versioned formula is not `keg_only`" do
fa = formula_auditor "foo@1.1", <<~RUBY, core_tap: true fa = formula_auditor "foo@1.1", <<~RUBY, core_tap: true

View File

@ -142,12 +142,26 @@ describe RuboCop::Cop::FormulaAudit::Urls do
"msg" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar should be " \ "msg" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar should be " \
"`https://search.maven.org/remotecontent?filepath=com/bar/foo/1.1/foo-1.1.jar`", "`https://search.maven.org/remotecontent?filepath=com/bar/foo/1.1/foo-1.1.jar`",
"col" => 2, "col" => 2,
}, {
"url" => "https://brew.sh/example-darwin.x86_64.tar.gz",
"msg" => "https://brew.sh/example-darwin.x86_64.tar.gz looks like a binary package, " \
"not a source archive. Homebrew/homebrew-core is source-only.",
"col" => 2,
"formula_tap" => "homebrew-core",
}, {
"url" => "https://brew.sh/example-darwin.amd64.tar.gz",
"msg" => "https://brew.sh/example-darwin.amd64.tar.gz looks like a binary package, " \
"not a source archive. Homebrew/homebrew-core is source-only.",
"col" => 2,
"formula_tap" => "homebrew-core",
}] }]
} }
context "When auditing urls" do context "When auditing urls" do
it "with offenses" do it "with offenses" do
formulae.each do |formula| formulae.each do |formula|
allow_any_instance_of(RuboCop::Cop::FormulaCop).to receive(:formula_tap)
.and_return(formula["formula_tap"])
source = <<~RUBY source = <<~RUBY
class Foo < Formula class Foo < Formula
desc "foo" desc "foo"