From 23933f3bdeaf8b16112f377b05d69b82381c90ed Mon Sep 17 00:00:00 2001 From: Alex Evanczuk Date: Thu, 22 Sep 2022 13:48:58 -0400 Subject: [PATCH] Fix bug where package protections doesn't look at packs/*/.rubocop_todo.yml (#27) * write failing test * Fix spec * move things to private * Bump version * start with set * rubocop --- Gemfile.lock | 2 +- lib/package_protections/private.rb | 33 +++++++++++++++++++ .../rubocop_protection_interface.rb | 25 ++------------ package_protections.gemspec | 2 +- spec/package_protections_spec.rb | 18 ++++++++++ 5 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 03d6d6a..3daff23 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - package_protections (2.1.0) + package_protections (2.1.1) activesupport parse_packwerk rubocop diff --git a/lib/package_protections/private.rb b/lib/package_protections/private.rb index cccc362..520d518 100644 --- a/lib/package_protections/private.rb +++ b/lib/package_protections/private.rb @@ -128,6 +128,39 @@ def self.private_cop_config(identifier) protected_packages.map { |p| [p.name, protection.custom_cop_config(p)] }.to_h end end + + sig { returns(T::Array[T::Hash[T.untyped, T.untyped]]) } + def self.rubocop_todo_ymls + @rubocop_todo_ymls = T.let(@rubocop_todo_ymls, T.nilable(T::Array[T::Hash[T.untyped, T.untyped]])) + @rubocop_todo_ymls ||= begin + todo_files = Pathname.glob('**/.rubocop_todo.yml') + todo_files.map do |todo_file| + YAML.load_file(todo_file) + end + end + end + + sig { void } + def self.bust_rubocop_todo_yml_cache + @rubocop_todo_ymls = nil + end + + sig { params(rule: String).returns(T::Set[String]) } + def self.exclude_for_rule(rule) + excludes = T.let(Set.new, T::Set[String]) + + Private.rubocop_todo_ymls.each do |todo_yml| + config = todo_yml[rule] + next if config.nil? + + exclude_list = config['Exclude'] + next if exclude_list.nil? + + excludes += exclude_list + end + + excludes + end end private_constant :Private diff --git a/lib/package_protections/rubocop_protection_interface.rb b/lib/package_protections/rubocop_protection_interface.rb index ea00feb..25326ee 100644 --- a/lib/package_protections/rubocop_protection_interface.rb +++ b/lib/package_protections/rubocop_protection_interface.rb @@ -71,20 +71,7 @@ def get_offenses_for_new_violations(new_violations) sig { void } def self.bust_rubocop_todo_yml_cache - @rubocop_todo_yml = nil - end - - sig { returns(T.untyped) } - def self.rubocop_todo_yml - @rubocop_todo_yml = T.let(@rubocop_todo_yml, T.untyped) - @rubocop_todo_yml ||= begin - todo_file = Pathname.new('.rubocop_todo.yml') - if todo_file.exist? - YAML.load_file(todo_file) - else - {} - end - end + Private.bust_rubocop_todo_yml_cache end sig do @@ -93,7 +80,7 @@ def self.rubocop_todo_yml ).returns(T::Array[Offense]) end def get_offenses_for_existing_violations(protected_packages) - exclude_list = exclude_for_rule(cop_name) + exclude_list = Private.exclude_for_rule(cop_name) offenses = [] protected_packages.each do |package| @@ -146,13 +133,5 @@ def cop_configs(packages) ) ] end - - private - - sig { params(rule: String).returns(T::Set[String]) } - def exclude_for_rule(rule) - rule_config = RubocopProtectionInterface.rubocop_todo_yml[rule] || {} - Set.new(rule_config['Exclude'] || []) - end end end diff --git a/package_protections.gemspec b/package_protections.gemspec index 8a9c07a..d37bdac 100644 --- a/package_protections.gemspec +++ b/package_protections.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = 'package_protections' - spec.version = '2.1.0' + spec.version = '2.1.1' spec.authors = ['Gusto Engineers'] spec.email = ['stephan.hagemann@gusto.com'] spec.summary = 'Package protections for Rails apps' diff --git a/spec/package_protections_spec.rb b/spec/package_protections_spec.rb index b5df6cc..14f63fc 100644 --- a/spec/package_protections_spec.rb +++ b/spec/package_protections_spec.rb @@ -790,6 +790,24 @@ def get_new_violations ) end + it 'fails if any of this pack\'s files are in a pack-level rubocop TODO' do + apples_package_yml_with_namespace_protection_set_to_fail_on_any + + write_file('packs/apples/app/public/tool.rb', '') + write_file('packs/apples/.rubocop_todo.yml', <<~YML.strip) + PackageProtections/NamespacedUnderPackageName: + Exclude: + - packs/apples/app/public/tool.rb + YML + + offenses = PackageProtections.get_offenses(packages: get_packages, new_violations: []) + expect(offenses).to contain_exactly(1).offense + expect(offenses).to include_offense offense( + 'packs/apples', + '`packs/apples/app/public/tool.rb` should be namespaced under the package namespace', 'packs/apples/app/public/tool.rb', 'prevent_this_package_from_creating_other_namespaces' + ) + end + it 'succeeds if another pack\'s file is in the rubocop TODO' do apples_package_yml_with_namespace_protection_set_to_fail_on_any