Skip to content

Commit

Permalink
Allow ignore offences from YML file using load_ignore_config
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryTsepelev authored and palkan committed Jun 15, 2018
1 parent c823cc7 commit d3a27ff
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## master

- [PR [#13](https://github.com/palkan/isolator/pull/13)] Allow load ignored offences from YML file using `load_ignore_config`. ([@DmitryTsepelev][])

## 0.3.0 (2018-04-02)

- Add support for the [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner) gem. ([@Envek][])
Expand Down Expand Up @@ -42,3 +44,4 @@
[@TheSmartnik]: https://github.com/TheSmartnik
[@dsalahutdinov]: https://github.com/dsalahutdinov
[@Envek]: https://github.com/Envek
[@DmitryTsepelev]: https://github.com/DmitryTsepelev
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,22 @@ Isolator.adapters.sidekiq.ignore_if { Thread.current[:sidekiq_postpone] }

You can add as many _ignores_ as you want, the offense is registered iff all of them return false.

### Using with legacy Rails codebases

If you already have a huge Rails project it can be a tricky to turn Isolator on because you'll immediately get a lot of failed specs. If you want to fix detected issues one by one, you can list all of them in the special file `.isolator_todo.yml` in a following way:

```
sidekiq:
- app/models/user.rb:20
- app/models/sales/**/*.rb
```

All the exceptions raised in the listed lines will be ignored.

### Using with legacy Ruby codebases

If you are not using Rails, you'll have to load ignores from file manually, using `Isolator#load_ignore_config`, for instance `Isolator.load_ignore_config("./config/.isolator_todo.yml")`

## Custom Adapters

An adapter is just a combination of a _method wrapper_ and lifecycle hooks.
Expand Down
2 changes: 2 additions & 0 deletions lib/isolator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "isolator/notifier"
require "isolator/errors"
require "isolator/simple_hashie"
require "isolator/ignorer"

require "isolator/callbacks"
require "isolator/isolate"
Expand Down Expand Up @@ -105,6 +106,7 @@ def adapters

include Isolator::Isolate
include Isolator::Callbacks
include Isolator::Ignorer
end
end

Expand Down
39 changes: 39 additions & 0 deletions lib/isolator/ignorer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module Isolator
# Add .load_ignore_config function for ignoring patterns from file
module Ignorer
def load_ignore_config(path)
return unless File.exist?(path)

todos = YAML.load_file(path)

adapters.each do |id, adapter|
ignored_paths = todos.fetch(id, [])
configure_adapter(adapter, ignored_paths)
end
end

private

def configure_adapter(adapter, ignored_paths)
ignores = build_ignore_list(ignored_paths)
return if ignores.blank?

regex = Regexp.new("^.*(#{ignores.join('|')}):.*$")
adapter.ignore_if { caller.any? { |row| regex =~ row } }
end

def build_ignore_list(ignored_paths)
ignored_paths.each_with_object([]) do |path, result|
ignored_files = Dir[path]

if ignored_files.blank?
result << path.to_s
else
result.concat(ignored_files)
end
end
end
end
end
2 changes: 2 additions & 0 deletions lib/isolator/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class Railtie < ::Rails::Railtie # :nodoc:
# (when all deps are likely to be loaded).
load File.join(__dir__, "adapters.rb")

Isolator.load_ignore_config(Rails.root.join(".isolator_todo.yml"))

next unless Rails.env.test?

if defined?(::ActiveRecord::TestFixtures)
Expand Down
81 changes: 81 additions & 0 deletions spec/isolator/ignorer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

require "spec_helper"

describe "Ignorer" do
TODO_PATH = ".isolator_todo.yml"

before(:all) do
module ::Isolator::Danger # rubocop:disable Style/ClassAndModuleChildren
def self.call_masked(a, b)
a + b
end

def self.call_unmasked(a, b)
a + b
end
end

Isolator.isolate :todo_masked_adapter,
target: ::Isolator::Danger.singleton_class,
method_name: :call_masked

Isolator.isolate :todo_unmasked_adapter,
target: ::Isolator::Danger.singleton_class,
method_name: :call_unmasked
end

after(:all) do
Isolator.send(:remove_const, "Danger")
Isolator.adapters.delete("todo_masked_adapter")
Isolator.adapters.delete("todo_unmasked_adapter")
end

before do
allow(Isolator).to receive(:within_transaction?) { true }
end

subject { ::Isolator::Danger }

specify do
expect { subject.call_masked(1, 2) }.to raise_error(Isolator::UnsafeOperationError)
expect { subject.call_unmasked(1, 2) }.to raise_error(Isolator::UnsafeOperationError)
end

context "unmasked todos" do
before(:each) do
allow(File).to receive(:exist?).with(TODO_PATH).and_return(true)

allow(YAML).to receive(:load_file).with(TODO_PATH).and_return(
"todo_unmasked_adapter" => ["spec/isolator/ignorer_spec.rb:58"],
"wrong_adapter" => ["spec/isolator/ignorer_spec.rb:62"]
)

Isolator.load_ignore_config(TODO_PATH)
end

it "doesn't raise when ignored" do
expect { subject.call_unmasked(1, 2) }.not_to raise_error
end

it "raise when wrong operator is ignored" do
expect { subject.call_unmasked(1, 2) }.to raise_error
end
end

context "masked todos" do
before(:each) do
allow(File).to receive(:exist?).with(TODO_PATH).and_return(true)

allow(YAML).to receive(:load_file).with(TODO_PATH).and_return(
"todo_masked_adapter" => ["spec/isolator/**/*.rb"]
)

Isolator.load_ignore_config(TODO_PATH)
end

it "doesn't raise when ignored via mask" do
expect { subject.call_masked(1, 2) }.not_to raise_error
end
end
end

0 comments on commit d3a27ff

Please sign in to comment.