From 857393ccfb026eb414c3d4d4c4a6eedda95dc314 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 5 Apr 2020 15:22:06 +0100 Subject: [PATCH] Audit correct `uses_from_macos` usage with RuboCop - This builds on @jonchang's work that started in #6265. - We now use `uses_from_macos` to declare dependencies that are implicit on macOS because they ship with macOS, but they're needed on Linux. We have to be sure that the dependencies people specify as `uses_from_macos` are actually shipped with macOS. So, we maintain a safelist of those dependencies and check against it. - Also add more legitimate `uses_from_macos` dependencies to the list. - This is runnable with `brew audit --only-cops=FormulaAudit/UsesFromMacos`. - It produces different number of failures on macOS vs. Linux, because apparently we've not synced Homebrew/linuxbrew-core upstream thoroughly enough yet. - Originally this was designed as a `--strict` audit, but we flipped it to be a normal audit because - to quote Mike - this is "sufficiently robust" now. --- Library/Homebrew/rubocops.rb | 1 + Library/Homebrew/rubocops/uses_from_macos.rb | 52 +++++++++++++++++++ Library/Homebrew/test/.rubocop_todo.yml | 1 + .../test/rubocops/uses_from_macos_spec.rb | 19 +++++++ 4 files changed, 73 insertions(+) create mode 100644 Library/Homebrew/rubocops/uses_from_macos.rb create mode 100644 Library/Homebrew/test/rubocops/uses_from_macos_spec.rb diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb index 8319d11158..0ea87b5661 100644 --- a/Library/Homebrew/rubocops.rb +++ b/Library/Homebrew/rubocops.rb @@ -18,5 +18,6 @@ require "rubocops/options" require "rubocops/urls" require "rubocops/lines" require "rubocops/class" +require "rubocops/uses_from_macos" require "rubocops/rubocop-cask" diff --git a/Library/Homebrew/rubocops/uses_from_macos.rb b/Library/Homebrew/rubocops/uses_from_macos.rb new file mode 100644 index 0000000000..33bed6805e --- /dev/null +++ b/Library/Homebrew/rubocops/uses_from_macos.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require "rubocops/extend/formula" + +module RuboCop + module Cop + module FormulaAudit + # This cop audits `uses_from_macos` dependencies in formulae + class UsesFromMacos < FormulaCop + ALLOWED_USES_FROM_MACOS_DEPS = %w[ + bison + bzip2 + curl + expat + expect + flex + groff + libffi + libxml2 + libxslt + ncurses + m4 + perl + php + python@2 + ruby + sqlite + texinfo + unzip + vim + xz + zlib + zsh + ].freeze + + def audit_formula(_node, _class_node, _parent_class_node, body_node) + find_method_with_args(body_node, :uses_from_macos, /^"(.+)"/).each do |method| + dep = if parameters(method).first.class == RuboCop::AST::StrNode + parameters(method).first + elsif parameters(method).first.class == RuboCop::AST::HashNode + parameters(method).first.keys.first + end + + next if ALLOWED_USES_FROM_MACOS_DEPS.include?(string_content(dep)) + + problem "`uses_from_macos` should only be used for macOS dependencies, not #{string_content(dep)}." + end + end + end + end + end +end diff --git a/Library/Homebrew/test/.rubocop_todo.yml b/Library/Homebrew/test/.rubocop_todo.yml index 5d4d426c9c..7767ec9294 100644 --- a/Library/Homebrew/test/.rubocop_todo.yml +++ b/Library/Homebrew/test/.rubocop_todo.yml @@ -48,6 +48,7 @@ RSpec/FilePath: - 'rubocops/options_spec.rb' - 'rubocops/patches_spec.rb' - 'rubocops/text_spec.rb' + - 'rubocops/uses_from_macos_spec.rb' - 'search_spec.rb' - 'string_spec.rb' - 'system_command_result_spec.rb' diff --git a/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb b/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb new file mode 100644 index 0000000000..35f27cc920 --- /dev/null +++ b/Library/Homebrew/test/rubocops/uses_from_macos_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "rubocops/uses_from_macos" + +describe RuboCop::Cop::FormulaAudit::UsesFromMacos do + subject(:cop) { described_class.new } + + it "when auditing uses_from_macos dependencies" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + homepage "https://brew.sh" + + uses_from_macos "postgresql" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `uses_from_macos` should only be used for macOS dependencies, not postgresql. + end + RUBY + end +end