From 890c83f2a583d45513115d4f9a0c107fa68a6a10 Mon Sep 17 00:00:00 2001 From: Aidan Feldman Date: Sun, 5 Apr 2015 02:16:01 -0400 Subject: [PATCH 01/73] add hint for NoMethodError --- lib/better_errors/raised_exception.rb | 18 +++++++++++++++- lib/better_errors/templates/main.erb | 9 +++++--- spec/better_errors/raised_exception_spec.rb | 24 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/better_errors/raised_exception.rb b/lib/better_errors/raised_exception.rb index 4057d5bf..c661e8ef 100644 --- a/lib/better_errors/raised_exception.rb +++ b/lib/better_errors/raised_exception.rb @@ -1,7 +1,7 @@ # @private module BetterErrors class RaisedException - attr_reader :exception, :message, :backtrace + attr_reader :exception, :message, :backtrace, :hint def initialize(exception) if exception.respond_to?(:original_exception) && exception.original_exception @@ -12,6 +12,7 @@ def initialize(exception) @message = exception.message setup_backtrace + setup_hint massage_syntax_error end @@ -62,5 +63,20 @@ def massage_syntax_error end end end + + def setup_hint + if exception.is_a?(NoMethodError) + matches = /\Aundefined method `([^']+)' for ([^:]+):(\w+)\z/.match(message) + method = matches[1] + val = matches[2] + klass = matches[3] + + if val == "nil" + @hint = "Something is `nil` when it probably shouldn't be." + else + @hint = "`#{method}` is being called on a `#{klass}`, which probably isn't the type you were expecting." + end + end + end end end diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb index e1a7f9ed..35f1fbde 100644 --- a/lib/better_errors/templates/main.erb +++ b/lib/better_errors/templates/main.erb @@ -90,7 +90,7 @@ nav.sidebar, .frame_info { position: fixed; - top: 95px; + top: 102px; bottom: 0; box-sizing: border-box; @@ -102,7 +102,7 @@ nav.sidebar { width: 40%; left: 20px; - top: 115px; + top: 122px; bottom: 20px; } @@ -131,7 +131,7 @@ header.exception { padding: 18px 20px; - height: 59px; + height: 66px; min-height: 59px; overflow: hidden; @@ -733,6 +733,9 @@

<%= exception.type %> at <%= request_path %>

<%= exception.message %>

+ <% if exception.hint %> +

Hint: <%= exception.hint %>

+ <% end %>
diff --git a/spec/better_errors/raised_exception_spec.rb b/spec/better_errors/raised_exception_spec.rb index 435c0139..67cac201 100644 --- a/spec/better_errors/raised_exception_spec.rb +++ b/spec/better_errors/raised_exception_spec.rb @@ -68,5 +68,29 @@ module BetterErrors subject.backtrace.first.line.should == 11 end end + + context "when the exception is a NoMethodError" do + let(:exception) { + begin + val.foo + rescue NoMethodError => e + e + end + } + + context "on `nil`" do + let(:val) { nil } + + its(:type) { should == NoMethodError } + its(:hint) { should == "Something is `nil` when it probably shouldn't be." } + end + + context "on other values" do + let(:val) { 42 } + + its(:type) { should == NoMethodError } + its(:hint) { should == "`foo` is being called on a `Fixnum`, which probably isn't the type you were expecting." } + end + end end end From 56340abf89f7fda9c256fadb212f1b4231aa68f3 Mon Sep 17 00:00:00 2001 From: Aidan Feldman Date: Sun, 5 Apr 2015 03:08:23 -0400 Subject: [PATCH 02/73] give hints for NameErrors --- lib/better_errors/raised_exception.rb | 9 ++++++++- spec/better_errors/raised_exception_spec.rb | 13 +++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/better_errors/raised_exception.rb b/lib/better_errors/raised_exception.rb index c661e8ef..38528a41 100644 --- a/lib/better_errors/raised_exception.rb +++ b/lib/better_errors/raised_exception.rb @@ -65,7 +65,8 @@ def massage_syntax_error end def setup_hint - if exception.is_a?(NoMethodError) + case exception + when NoMethodError matches = /\Aundefined method `([^']+)' for ([^:]+):(\w+)\z/.match(message) method = matches[1] val = matches[2] @@ -76,6 +77,12 @@ def setup_hint else @hint = "`#{method}` is being called on a `#{klass}`, which probably isn't the type you were expecting." end + when NameError + matches = /\Aundefined local variable or method `([^']+)' for/.match(message) + if matches + method_or_var = matches[1] + @hint = "`#{method_or_var}` is probably misspelled." + end end end end diff --git a/spec/better_errors/raised_exception_spec.rb b/spec/better_errors/raised_exception_spec.rb index 67cac201..6ffe86b1 100644 --- a/spec/better_errors/raised_exception_spec.rb +++ b/spec/better_errors/raised_exception_spec.rb @@ -69,6 +69,19 @@ module BetterErrors end end + context "when the exception is a NameError" do + let(:exception) { + begin + foo + rescue NameError => e + e + end + } + + its(:type) { should == NameError } + its(:hint) { should == "`foo` is probably misspelled." } + end + context "when the exception is a NoMethodError" do let(:exception) { begin From 081fa8454913cc443d285b2bd247fbaf79f0e070 Mon Sep 17 00:00:00 2001 From: Aidan Feldman Date: Sun, 5 Apr 2015 03:13:44 -0400 Subject: [PATCH 03/73] more cautious checking for NoMethodError hint --- lib/better_errors/raised_exception.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/better_errors/raised_exception.rb b/lib/better_errors/raised_exception.rb index 38528a41..39f11c4f 100644 --- a/lib/better_errors/raised_exception.rb +++ b/lib/better_errors/raised_exception.rb @@ -68,14 +68,16 @@ def setup_hint case exception when NoMethodError matches = /\Aundefined method `([^']+)' for ([^:]+):(\w+)\z/.match(message) - method = matches[1] - val = matches[2] - klass = matches[3] + if matches + method = matches[1] + val = matches[2] + klass = matches[3] - if val == "nil" - @hint = "Something is `nil` when it probably shouldn't be." - else - @hint = "`#{method}` is being called on a `#{klass}`, which probably isn't the type you were expecting." + if val == "nil" + @hint = "Something is `nil` when it probably shouldn't be." + else + @hint = "`#{method}` is being called on a `#{klass}`, which probably isn't the type you were expecting." + end end when NameError matches = /\Aundefined local variable or method `([^']+)' for/.match(message) From 0ac88dcfd60a5340ae7212d3a07a38ce8e65892e Mon Sep 17 00:00:00 2001 From: Addison Martin Date: Thu, 1 Oct 2020 20:10:23 -0400 Subject: [PATCH 04/73] Fixed 'uninitialized constant BetterErrors::Middleware::VERSION' in lib/better_errors/middleware.rb by using BetterErrors::Version, not the nonexistent VERSION constant of Middleware. --- lib/better_errors/middleware.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/better_errors/middleware.rb b/lib/better_errors/middleware.rb index 8215c70b..3a437819 100644 --- a/lib/better_errors/middleware.rb +++ b/lib/better_errors/middleware.rb @@ -40,7 +40,7 @@ def self.allow_ip!(addr) allow_ip! "127.0.0.0/8" allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support - CSRF_TOKEN_COOKIE_NAME = "BetterErrors-#{VERSION}-CSRF-Token" + CSRF_TOKEN_COOKIE_NAME = "BetterErrors-#{BetterErrors::VERSION}-CSRF-Token" # A new instance of BetterErrors::Middleware # From 527f8b092bbf7f8967aeea313470c9053ca3118a Mon Sep 17 00:00:00 2001 From: Rafael Nunes Date: Fri, 2 Oct 2020 12:15:57 +1000 Subject: [PATCH 05/73] Fix CSRF_TOKEN_COOKIE_NAME wrong reference to VERSION constant --- lib/better_errors/middleware.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/better_errors/middleware.rb b/lib/better_errors/middleware.rb index 8215c70b..3a437819 100644 --- a/lib/better_errors/middleware.rb +++ b/lib/better_errors/middleware.rb @@ -40,7 +40,7 @@ def self.allow_ip!(addr) allow_ip! "127.0.0.0/8" allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support - CSRF_TOKEN_COOKIE_NAME = "BetterErrors-#{VERSION}-CSRF-Token" + CSRF_TOKEN_COOKIE_NAME = "BetterErrors-#{BetterErrors::VERSION}-CSRF-Token" # A new instance of BetterErrors::Middleware # From 90789f99ff1a5575f79758db562c810d20d64a25 Mon Sep 17 00:00:00 2001 From: Rafael Nunes Date: Fri, 2 Oct 2020 21:35:12 +1000 Subject: [PATCH 06/73] Moves version require up to guarantee dependants can access it --- lib/better_errors.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/better_errors.rb b/lib/better_errors.rb index ee7a48bd..8cd6b7ec 100644 --- a/lib/better_errors.rb +++ b/lib/better_errors.rb @@ -3,6 +3,7 @@ require "coderay" require "uri" +require "better_errors/version" require "better_errors/code_formatter" require "better_errors/inspectable_value" require "better_errors/error_page" @@ -10,7 +11,6 @@ require "better_errors/raised_exception" require "better_errors/repl" require "better_errors/stack_frame" -require "better_errors/version" module BetterErrors POSSIBLE_EDITOR_PRESETS = [ From 65c562c3da658908191e87d5debe86d877d5fcbe Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Fri, 2 Oct 2020 23:28:13 -0400 Subject: [PATCH 07/73] Release 2.8.3 --- lib/better_errors/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/better_errors/version.rb b/lib/better_errors/version.rb index e49a5c48..1476281a 100644 --- a/lib/better_errors/version.rb +++ b/lib/better_errors/version.rb @@ -1,3 +1,3 @@ module BetterErrors - VERSION = "2.8.2" + VERSION = "2.8.3" end From 931ffa04cf7153f2d54c30eac798017368447e6e Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Fri, 30 Oct 2020 16:39:44 -0400 Subject: [PATCH 08/73] Mention path in text response --- lib/better_errors/templates/text.erb | 7 +++++-- spec/better_errors/middleware_spec.rb | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/better_errors/templates/text.erb b/lib/better_errors/templates/text.erb index f51f1eed..0a99cc4b 100644 --- a/lib/better_errors/templates/text.erb +++ b/lib/better_errors/templates/text.erb @@ -1,7 +1,10 @@ <%== text_heading("=", "%s at %s" % [exception_type, request_path]) %> -> <%== exception_message %> -<% if backtrace_frames.any? %> +<%== exception_message %> + +> To access an interactive console with this error, point your browser to: /__better_errors + +<% if backtrace_frames.any? -%> <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %> diff --git a/spec/better_errors/middleware_spec.rb b/spec/better_errors/middleware_spec.rb index 4f5e9bcb..0cdd8216 100644 --- a/spec/better_errors/middleware_spec.rb +++ b/spec/better_errors/middleware_spec.rb @@ -147,8 +147,8 @@ module BetterErrors it "shows the exception as-is" do expect(status).to eq(500) - expect(body).to match(/\n> Second Exception\n/) - expect(body).not_to match(/\n> First Exception\n/) + expect(body).to match(/\nSecond Exception\n/) + expect(body).not_to match(/\nFirst Exception\n/) end end From d9a891ba99c99dee6e7fe29faf6cda9104dd98ad Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Sat, 31 Oct 2020 12:17:58 -0400 Subject: [PATCH 09/73] Refactor to ExceptionHint Use named regex groups and support for did_you_mean-augmented NoMethodError. --- lib/better_errors/exception_hint.rb | 29 +++++++++++++ lib/better_errors/raised_exception.rb | 24 ++--------- spec/better_errors/exception_hint_spec.rb | 46 ++++++++++++++++++++ spec/better_errors/raised_exception_spec.rb | 47 +++++++-------------- 4 files changed, 94 insertions(+), 52 deletions(-) create mode 100644 lib/better_errors/exception_hint.rb create mode 100644 spec/better_errors/exception_hint_spec.rb diff --git a/lib/better_errors/exception_hint.rb b/lib/better_errors/exception_hint.rb new file mode 100644 index 00000000..31953504 --- /dev/null +++ b/lib/better_errors/exception_hint.rb @@ -0,0 +1,29 @@ +module BetterErrors + class ExceptionHint + def initialize(exception) + @exception = exception + end + + def hint + case exception + when NoMethodError + /\Aundefined method `(?[^']+)' for (?[^:]+):(?\w+)/.match(exception.message) do |match| + if match[:val] == "nil" + return "Something is `nil` when it probably shouldn't be." + else + return "`#{match[:method]}` is being called on a `#{match[:klass]}` object, "\ + "which might not be the type of object you were expecting." + end + end + when NameError + /\Aundefined local variable or method `(?[^']+)' for/.match(exception.message) do |match| + return "`#{match[:method]}` is probably misspelled." + end + end + end + + private + + attr_reader :exception + end +end diff --git a/lib/better_errors/raised_exception.rb b/lib/better_errors/raised_exception.rb index a581b2b2..8c4a7ccc 100644 --- a/lib/better_errors/raised_exception.rb +++ b/lib/better_errors/raised_exception.rb @@ -1,3 +1,5 @@ +require 'better_errors/exception_hint' + # @private module BetterErrors class RaisedException @@ -81,27 +83,7 @@ def massage_syntax_error end def setup_hint - case exception - when NoMethodError - matches = /\Aundefined method `([^']+)' for ([^:]+):(\w+)\z/.match(message) - if matches - method = matches[1] - val = matches[2] - klass = matches[3] - - if val == "nil" - @hint = "Something is `nil` when it probably shouldn't be." - else - @hint = "`#{method}` is being called on a `#{klass}`, which probably isn't the type you were expecting." - end - end - when NameError - matches = /\Aundefined local variable or method `([^']+)' for/.match(message) - if matches - method_or_var = matches[1] - @hint = "`#{method_or_var}` is probably misspelled." - end - end + @hint = ExceptionHint.new(exception).hint end end end diff --git a/spec/better_errors/exception_hint_spec.rb b/spec/better_errors/exception_hint_spec.rb new file mode 100644 index 00000000..fcacc088 --- /dev/null +++ b/spec/better_errors/exception_hint_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +RSpec.describe BetterErrors::ExceptionHint do + let(:described_instance) { described_class.new(exception) } + + describe '#hint' do + subject(:hint) { described_instance.hint } + + context "when the exception is a NameError" do + let(:exception) { + begin + foo + rescue NameError => e + e + end + } + + it { is_expected.to eq("`foo` is probably misspelled.") } + end + + context "when the exception is a NoMethodError" do + let(:exception) { + begin + val.foo + rescue NoMethodError => e + e + end + } + + context "on `nil`" do + let(:val) { nil } + + it { is_expected.to eq("Something is `nil` when it probably shouldn't be.") } + end + + context "on other values" do + let(:val) { 42 } + + it { + is_expected.to eq("`foo` is being called on a `Integer` object"\ + ", which might not be the type of object you were expecting.") + } + end + end + end +end diff --git a/spec/better_errors/raised_exception_spec.rb b/spec/better_errors/raised_exception_spec.rb index 45fa730d..1a1df8ca 100644 --- a/spec/better_errors/raised_exception_spec.rb +++ b/spec/better_errors/raised_exception_spec.rb @@ -4,7 +4,12 @@ module BetterErrors describe RaisedException do let(:exception) { RuntimeError.new("whoops") } - subject { RaisedException.new(exception) } + subject(:described_instance) { RaisedException.new(exception) } + + before do + allow(BetterErrors::ExceptionHint).to receive(:new).and_return(exception_hint) + end + let(:exception_hint) { instance_double(BetterErrors::ExceptionHint, hint: nil) } its(:exception) { is_expected.to eq exception } its(:message) { is_expected.to eq "whoops" } @@ -104,40 +109,20 @@ def cause end end - context "when the exception is a NameError" do - let(:exception) { - begin - foo - rescue NameError => e - e - end - } - - its(:type) { should == NameError } - its(:hint) { should == "`foo` is probably misspelled." } - end + describe '#hint' do + subject(:hint) { described_instance.hint } - context "when the exception is a NoMethodError" do - let(:exception) { - begin - val.foo - rescue NoMethodError => e - e - end - } - - context "on `nil`" do - let(:val) { nil } - - its(:type) { should == NoMethodError } - its(:hint) { should == "Something is `nil` when it probably shouldn't be." } + it 'uses ExceptionHint to get a hint for the exception' do + hint + expect(BetterErrors::ExceptionHint).to have_received(:new).with(exception) end - context "on other values" do - let(:val) { 42 } + context "when ExceptionHint returns a string" do + let(:exception_hint) { instance_double(BetterErrors::ExceptionHint, hint: "Hint text") } - its(:type) { should == NoMethodError } - its(:hint) { should == "`foo` is being called on a `Fixnum`, which probably isn't the type you were expecting." } + it 'returns the value from ExceptionHint' do + expect(hint).to eq("Hint text") + end end end end From f9432b9b9b8bd5ce7f4ba2c1b57ccf0040984f8f Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Sat, 31 Oct 2020 12:25:09 -0400 Subject: [PATCH 10/73] Don't show hint for anonymous classes --- lib/better_errors/exception_hint.rb | 2 +- spec/better_errors/exception_hint_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/better_errors/exception_hint.rb b/lib/better_errors/exception_hint.rb index 31953504..a873c770 100644 --- a/lib/better_errors/exception_hint.rb +++ b/lib/better_errors/exception_hint.rb @@ -10,7 +10,7 @@ def hint /\Aundefined method `(?[^']+)' for (?[^:]+):(?\w+)/.match(exception.message) do |match| if match[:val] == "nil" return "Something is `nil` when it probably shouldn't be." - else + elsif !match[:klass].start_with? /\A0x/ return "`#{match[:method]}` is being called on a `#{match[:klass]}` object, "\ "which might not be the type of object you were expecting." end diff --git a/spec/better_errors/exception_hint_spec.rb b/spec/better_errors/exception_hint_spec.rb index fcacc088..68412b4b 100644 --- a/spec/better_errors/exception_hint_spec.rb +++ b/spec/better_errors/exception_hint_spec.rb @@ -33,6 +33,12 @@ it { is_expected.to eq("Something is `nil` when it probably shouldn't be.") } end + context 'on an unnamed object type' do + let(:val) { Class.new } + + it { is_expected.to be_nil } + end + context "on other values" do let(:val) { 42 } From 20ae3b738b9cc0bf8341284024b4fc88615a6a32 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 16:25:05 -0500 Subject: [PATCH 11/73] Github Actions --- .github/workflows/ruby.yml | 74 +++++++++++++++++++++++++ .travis.yml | 111 ------------------------------------- 2 files changed, 74 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/ruby.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 00000000..db93c630 --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,74 @@ +name: Test + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + + runs-on: ubuntu-latest + + strategy: + matrix: + ruby: + - 2.2.10 + - 2.3.8 + - 2.4.9 + - 2.5.7 + - 2.6.5 + - 2.7.0 + - ruby-head + - truffleruby-head + gemfile: + - gemfiles/rails42.gemfile + - gemfiles/rails50.gemfile + - gemfiles/rails51.gemfile + - gemfiles/rails52.gemfile + - gemfiles/rails60.gemfile + - gemfiles/rails42_haml.gemfile + - gemfiles/rails50_haml.gemfile + - gemfiles/rails51_haml.gemfile + - gemfiles/rails52_haml.gemfile + - gemfiles/rails60_haml.gemfile + - gemfiles/rails42_boc.gemfile + - gemfiles/rails50_boc.gemfile + - gemfiles/rails51_boc.gemfile + - gemfiles/rails52_boc.gemfile + - gemfiles/rails60_boc.gemfile + - gemfiles/rack.gemfile + - gemfiles/rack_boc.gemfile + - gemfiles/pry09.gemfile + - gemfiles/pry010.gemfile + - gemfiles/pry011.gemfile + + steps: + - uses: actions/checkout@v2 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles('gemfiles/*.gemfile') }} + restore-keys: | + ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} + ${{ runner.os }}-ruby-${{ matrix.ruby }} + + - name: Configure bundler + run: bundle config path vendor/bundle + + - name: Bundle install + run: bundle install --jobs 4 --retry 3 + env: + BUNDLE_GEMFILE: ${{ matrix.gemfile }} + + - name: RSpec + run: bundle exec rspec -f doc --color + env: + BUNDLE_GEMFILE: ${{ matrix.gemfile }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0193b6d9..00000000 --- a/.travis.yml +++ /dev/null @@ -1,111 +0,0 @@ -language: ruby -cache: bundler -notifications: - webhooks: - # With COVERALLS_PARALLEL, coverage information sent to coveralls will not be processed until - # this webhook is sent. - # https://coveralls.zendesk.com/hc/en-us/articles/203484329-Parallel-Build-Webhook - - secure: "YnHYbTq51ySistjvOxsuNhyg4GLuUffEJstTYeGYXiBF7HG5h43IVYo8KNuLzwkgsOYBcNo+YMdQX7qCqJffSbhsr1FZRSzBmjFFxcyD4hu+ukM2theZ4mePVAZiePscYvQPRNY4hIb4d3egStJEytkalDhB3sOebF57tIaCssg=" -rvm: - - 2.2.10 - - 2.3.8 - - 2.4.9 - - 2.5.7 - - 2.6.5 - - 2.7.0 - - ruby-head - - truffleruby-head -gemfile: - - gemfiles/rails42.gemfile - - gemfiles/rails50.gemfile - - gemfiles/rails51.gemfile - - gemfiles/rails52.gemfile - - gemfiles/rails60.gemfile - - gemfiles/rails42_haml.gemfile - - gemfiles/rails50_haml.gemfile - - gemfiles/rails51_haml.gemfile - - gemfiles/rails52_haml.gemfile - - gemfiles/rails60_haml.gemfile - - gemfiles/rails42_boc.gemfile - - gemfiles/rails50_boc.gemfile - - gemfiles/rails51_boc.gemfile - - gemfiles/rails52_boc.gemfile - - gemfiles/rails60_boc.gemfile - - gemfiles/rack.gemfile - - gemfiles/rack_boc.gemfile - - gemfiles/pry09.gemfile - - gemfiles/pry010.gemfile - - gemfiles/pry011.gemfile -matrix: - fast_finish: true - allow_failures: - - rvm: ruby-head - - gemfile: gemfiles/pry010.gemfile - - gemfile: gemfiles/pry011.gemfile - exclude: - - rvm: 2.2.10 - gemfile: gemfiles/rails60.gemfile - - rvm: 2.2.10 - gemfile: gemfiles/rails60_boc.gemfile - - rvm: 2.2.10 - gemfile: gemfiles/rails60_haml.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails42.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails42_boc.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails42_haml.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails60.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails60_boc.gemfile - - rvm: 2.3.8 - gemfile: gemfiles/rails60_haml.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails42.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails42_boc.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails42_haml.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails60.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails60_boc.gemfile - - rvm: 2.4.9 - gemfile: gemfiles/rails60_haml.gemfile - - rvm: 2.5.7 - gemfile: gemfiles/rails42.gemfile - - rvm: 2.5.7 - gemfile: gemfiles/rails42_boc.gemfile - - rvm: 2.5.7 - gemfile: gemfiles/rails42_haml.gemfile - - rvm: 2.6.5 - gemfile: gemfiles/rails42.gemfile - - rvm: 2.6.5 - gemfile: gemfiles/rails42_boc.gemfile - - rvm: 2.6.5 - gemfile: gemfiles/rails42_haml.gemfile - - rvm: 2.7.0 - gemfile: gemfiles/rails42.gemfile - - rvm: 2.7.0 - gemfile: gemfiles/rails42_boc.gemfile - - rvm: 2.7.0 - gemfile: gemfiles/rails42_haml.gemfile - - rvm: ruby-head - gemfile: gemfiles/rails42.gemfile - - rvm: ruby-head - gemfile: gemfiles/rails42_boc.gemfile - - rvm: ruby-head - gemfile: gemfiles/rails42_haml.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rails42_boc.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rails50_boc.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rails51_boc.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rails52_boc.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rails60_boc.gemfile - - rvm: truffleruby-head - gemfile: gemfiles/rack_boc.gemfile From a3895626b189ab6db306005c9c977c0e1a2f8e44 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 16:48:43 -0500 Subject: [PATCH 12/73] Improve job name --- .github/workflows/{ruby.yml => ci.yml} | 48 ++++++++++++++------------ 1 file changed, 25 insertions(+), 23 deletions(-) rename .github/workflows/{ruby.yml => ci.yml} (54%) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ci.yml similarity index 54% rename from .github/workflows/ruby.yml rename to .github/workflows/ci.yml index db93c630..910591cd 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Test +name: CI on: push: @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: + fail-fast: true matrix: ruby: - 2.2.10 @@ -23,26 +24,27 @@ jobs: - ruby-head - truffleruby-head gemfile: - - gemfiles/rails42.gemfile - - gemfiles/rails50.gemfile - - gemfiles/rails51.gemfile - - gemfiles/rails52.gemfile - - gemfiles/rails60.gemfile - - gemfiles/rails42_haml.gemfile - - gemfiles/rails50_haml.gemfile - - gemfiles/rails51_haml.gemfile - - gemfiles/rails52_haml.gemfile - - gemfiles/rails60_haml.gemfile - - gemfiles/rails42_boc.gemfile - - gemfiles/rails50_boc.gemfile - - gemfiles/rails51_boc.gemfile - - gemfiles/rails52_boc.gemfile - - gemfiles/rails60_boc.gemfile - - gemfiles/rack.gemfile - - gemfiles/rack_boc.gemfile - - gemfiles/pry09.gemfile - - gemfiles/pry010.gemfile - - gemfiles/pry011.gemfile + # These are located in the gemfiles/ folder + - rails42 + - rails50 + - rails51 + - rails52 + - rails60 + - rails42_haml + - rails50_haml + - rails51_haml + - rails52_haml + - rails60_haml + - rails42_boc + - rails50_boc + - rails51_boc + - rails52_boc + - rails60_boc + - rack + - rack_boc + - pry09 + - pry010 + - pry011 steps: - uses: actions/checkout@v2 @@ -66,9 +68,9 @@ jobs: - name: Bundle install run: bundle install --jobs 4 --retry 3 env: - BUNDLE_GEMFILE: ${{ matrix.gemfile }} + BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile - name: RSpec run: bundle exec rspec -f doc --color env: - BUNDLE_GEMFILE: ${{ matrix.gemfile }} + BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile From a5a77c96f43ceec57e6058402b6f1bccb3364baa Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 17:19:43 -0500 Subject: [PATCH 13/73] Update rubies and add `experimental` --- .github/workflows/ci.yml | 62 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 910591cd..8044499e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,16 +11,19 @@ jobs: runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: fail-fast: true matrix: + experimental: [false] ruby: - 2.2.10 - 2.3.8 - 2.4.9 - - 2.5.7 - - 2.6.5 - - 2.7.0 + - 2.5.8 + - 2.6.6 + - 2.7.2 - ruby-head - truffleruby-head gemfile: @@ -43,8 +46,57 @@ jobs: - rack - rack_boc - pry09 - - pry010 - - pry011 + exclude: + - { ruby: 2.2.10, gemfile: rails60, experimental: false } + - { ruby: 2.2.10, gemfile: rails60_boc, experimental: false } + - { ruby: 2.2.10, gemfile: rails60_haml, experimental: false } + - { ruby: 2.3.8, gemfile: rails42, experimental: false } + - { ruby: 2.3.8, gemfile: rails42_boc, experimental: false } + - { ruby: 2.3.8, gemfile: rails42_haml, experimental: false } + - { ruby: 2.3.8, gemfile: rails60, experimental: false } + - { ruby: 2.3.8, gemfile: rails60_boc, experimental: false } + - { ruby: 2.3.8, gemfile: rails60_haml, experimental: false } + - { ruby: 2.4.9, gemfile: rails42, experimental: false } + - { ruby: 2.4.9, gemfile: rails42_boc, experimental: false } + - { ruby: 2.4.9, gemfile: rails42_haml, experimental: false } + - { ruby: 2.4.9, gemfile: rails60, experimental: false } + - { ruby: 2.4.9, gemfile: rails60_boc, experimental: false } + - { ruby: 2.4.9, gemfile: rails60_haml, experimental: false } + - { ruby: 2.5.8, gemfile: rails42, experimental: false } + - { ruby: 2.5.8, gemfile: rails42_boc, experimental: false } + - { ruby: 2.5.8, gemfile: rails42_haml, experimental: false } + - { ruby: 2.6.6, gemfile: rails42, experimental: false } + - { ruby: 2.6.6, gemfile: rails42_boc, experimental: false } + - { ruby: 2.6.6, gemfile: rails42_haml, experimental: false } + - { ruby: 2.7.2, gemfile: rails42, experimental: false } + - { ruby: 2.7.2, gemfile: rails42_boc, experimental: false } + - { ruby: 2.7.2, gemfile: rails42_haml, experimental: false } + - { ruby: ruby-head, gemfile: rails42, experimental: false } + - { ruby: ruby-head, gemfile: rails42_boc, experimental: false } + - { ruby: ruby-head, gemfile: rails42_haml, experimental: false } + - { ruby: truffleruby-head, gemfile: rails42_boc, experimental: false } + - { ruby: truffleruby-head, gemfile: rails50_boc, experimental: false } + - { ruby: truffleruby-head, gemfile: rails51_boc, experimental: false } + - { ruby: truffleruby-head, gemfile: rails52_boc, experimental: false } + - { ruby: truffleruby-head, gemfile: rails60_boc, experimental: false } + - { ruby: truffleruby-head, gemfile: rack_boc, experimental: false } + include: + - { ruby: 2.2.10, gemfile: pry010, experimental: true } + - { ruby: 2.3.8, gemfile: pry010, experimental: true } + - { ruby: 2.4.9, gemfile: pry010, experimental: true } + - { ruby: 2.5.8, gemfile: pry010, experimental: true } + - { ruby: 2.6.6, gemfile: pry010, experimental: true } + - { ruby: 2.7.2, gemfile: pry010, experimental: true } + - { ruby: ruby-head, gemfile: pry010, experimental: true } + - { ruby: truffleruby-head, gemfile: pry010, experimental: true } + - { ruby: 2.2.10, gemfile: pry011, experimental: true } + - { ruby: 2.3.8, gemfile: pry011, experimental: true } + - { ruby: 2.4.9, gemfile: pry011, experimental: true } + - { ruby: 2.5.8, gemfile: pry011, experimental: true } + - { ruby: 2.6.6, gemfile: pry011, experimental: true } + - { ruby: 2.7.2, gemfile: pry011, experimental: true } + - { ruby: ruby-head, gemfile: pry011, experimental: true } + - { ruby: truffleruby-head, gemfile: pry011, experimental: true } steps: - uses: actions/checkout@v2 From 33c84cb79afbcc8ab598354c8bc2c409ab4a82af Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 17:26:18 -0500 Subject: [PATCH 14/73] Remove experimental flag --- .github/workflows/ci.yml | 86 +++++++++++++++------------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8044499e..3bedd97f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,12 +11,9 @@ jobs: runs-on: ubuntu-latest - continue-on-error: ${{ matrix.experimental }} - strategy: fail-fast: true matrix: - experimental: [false] ruby: - 2.2.10 - 2.3.8 @@ -47,56 +44,39 @@ jobs: - rack_boc - pry09 exclude: - - { ruby: 2.2.10, gemfile: rails60, experimental: false } - - { ruby: 2.2.10, gemfile: rails60_boc, experimental: false } - - { ruby: 2.2.10, gemfile: rails60_haml, experimental: false } - - { ruby: 2.3.8, gemfile: rails42, experimental: false } - - { ruby: 2.3.8, gemfile: rails42_boc, experimental: false } - - { ruby: 2.3.8, gemfile: rails42_haml, experimental: false } - - { ruby: 2.3.8, gemfile: rails60, experimental: false } - - { ruby: 2.3.8, gemfile: rails60_boc, experimental: false } - - { ruby: 2.3.8, gemfile: rails60_haml, experimental: false } - - { ruby: 2.4.9, gemfile: rails42, experimental: false } - - { ruby: 2.4.9, gemfile: rails42_boc, experimental: false } - - { ruby: 2.4.9, gemfile: rails42_haml, experimental: false } - - { ruby: 2.4.9, gemfile: rails60, experimental: false } - - { ruby: 2.4.9, gemfile: rails60_boc, experimental: false } - - { ruby: 2.4.9, gemfile: rails60_haml, experimental: false } - - { ruby: 2.5.8, gemfile: rails42, experimental: false } - - { ruby: 2.5.8, gemfile: rails42_boc, experimental: false } - - { ruby: 2.5.8, gemfile: rails42_haml, experimental: false } - - { ruby: 2.6.6, gemfile: rails42, experimental: false } - - { ruby: 2.6.6, gemfile: rails42_boc, experimental: false } - - { ruby: 2.6.6, gemfile: rails42_haml, experimental: false } - - { ruby: 2.7.2, gemfile: rails42, experimental: false } - - { ruby: 2.7.2, gemfile: rails42_boc, experimental: false } - - { ruby: 2.7.2, gemfile: rails42_haml, experimental: false } - - { ruby: ruby-head, gemfile: rails42, experimental: false } - - { ruby: ruby-head, gemfile: rails42_boc, experimental: false } - - { ruby: ruby-head, gemfile: rails42_haml, experimental: false } - - { ruby: truffleruby-head, gemfile: rails42_boc, experimental: false } - - { ruby: truffleruby-head, gemfile: rails50_boc, experimental: false } - - { ruby: truffleruby-head, gemfile: rails51_boc, experimental: false } - - { ruby: truffleruby-head, gemfile: rails52_boc, experimental: false } - - { ruby: truffleruby-head, gemfile: rails60_boc, experimental: false } - - { ruby: truffleruby-head, gemfile: rack_boc, experimental: false } - include: - - { ruby: 2.2.10, gemfile: pry010, experimental: true } - - { ruby: 2.3.8, gemfile: pry010, experimental: true } - - { ruby: 2.4.9, gemfile: pry010, experimental: true } - - { ruby: 2.5.8, gemfile: pry010, experimental: true } - - { ruby: 2.6.6, gemfile: pry010, experimental: true } - - { ruby: 2.7.2, gemfile: pry010, experimental: true } - - { ruby: ruby-head, gemfile: pry010, experimental: true } - - { ruby: truffleruby-head, gemfile: pry010, experimental: true } - - { ruby: 2.2.10, gemfile: pry011, experimental: true } - - { ruby: 2.3.8, gemfile: pry011, experimental: true } - - { ruby: 2.4.9, gemfile: pry011, experimental: true } - - { ruby: 2.5.8, gemfile: pry011, experimental: true } - - { ruby: 2.6.6, gemfile: pry011, experimental: true } - - { ruby: 2.7.2, gemfile: pry011, experimental: true } - - { ruby: ruby-head, gemfile: pry011, experimental: true } - - { ruby: truffleruby-head, gemfile: pry011, experimental: true } + - { ruby: 2.2.10, gemfile: rails60 } + - { ruby: 2.2.10, gemfile: rails60_boc } + - { ruby: 2.2.10, gemfile: rails60_haml } + - { ruby: 2.3.8, gemfile: rails42 } + - { ruby: 2.3.8, gemfile: rails42_boc } + - { ruby: 2.3.8, gemfile: rails42_haml } + - { ruby: 2.3.8, gemfile: rails60 } + - { ruby: 2.3.8, gemfile: rails60_boc } + - { ruby: 2.3.8, gemfile: rails60_haml } + - { ruby: 2.4.9, gemfile: rails42 } + - { ruby: 2.4.9, gemfile: rails42_boc } + - { ruby: 2.4.9, gemfile: rails42_haml } + - { ruby: 2.4.9, gemfile: rails60 } + - { ruby: 2.4.9, gemfile: rails60_boc } + - { ruby: 2.4.9, gemfile: rails60_haml } + - { ruby: 2.5.8, gemfile: rails42 } + - { ruby: 2.5.8, gemfile: rails42_boc } + - { ruby: 2.5.8, gemfile: rails42_haml } + - { ruby: 2.6.6, gemfile: rails42 } + - { ruby: 2.6.6, gemfile: rails42_boc } + - { ruby: 2.6.6, gemfile: rails42_haml } + - { ruby: 2.7.2, gemfile: rails42 } + - { ruby: 2.7.2, gemfile: rails42_boc } + - { ruby: 2.7.2, gemfile: rails42_haml } + - { ruby: ruby-head, gemfile: rails42 } + - { ruby: ruby-head, gemfile: rails42_boc } + - { ruby: ruby-head, gemfile: rails42_haml } + - { ruby: truffleruby-head, gemfile: rails42_boc } + - { ruby: truffleruby-head, gemfile: rails50_boc } + - { ruby: truffleruby-head, gemfile: rails51_boc } + - { ruby: truffleruby-head, gemfile: rails52_boc } + - { ruby: truffleruby-head, gemfile: rails60_boc } + - { ruby: truffleruby-head, gemfile: rack_boc } steps: - uses: actions/checkout@v2 From afda98bae89ffbca28936584fc04459e7f8053d3 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 17:48:41 -0500 Subject: [PATCH 15/73] Remove ruby-head, use minor Ruby version and use latest truffleruby release --- .github/workflows/ci.yml | 82 ++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3bedd97f..8b0d7022 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,14 +15,14 @@ jobs: fail-fast: true matrix: ruby: - - 2.2.10 - - 2.3.8 - - 2.4.9 - - 2.5.8 - - 2.6.6 - - 2.7.2 - - ruby-head - - truffleruby-head + - 2.2 + - 2.3 + - 2.4 + - 2.5 + - 2.6 + - 2.7 + # - ruby-head + - truffleruby gemfile: # These are located in the gemfiles/ folder - rails42 @@ -44,39 +44,39 @@ jobs: - rack_boc - pry09 exclude: - - { ruby: 2.2.10, gemfile: rails60 } - - { ruby: 2.2.10, gemfile: rails60_boc } - - { ruby: 2.2.10, gemfile: rails60_haml } - - { ruby: 2.3.8, gemfile: rails42 } - - { ruby: 2.3.8, gemfile: rails42_boc } - - { ruby: 2.3.8, gemfile: rails42_haml } - - { ruby: 2.3.8, gemfile: rails60 } - - { ruby: 2.3.8, gemfile: rails60_boc } - - { ruby: 2.3.8, gemfile: rails60_haml } - - { ruby: 2.4.9, gemfile: rails42 } - - { ruby: 2.4.9, gemfile: rails42_boc } - - { ruby: 2.4.9, gemfile: rails42_haml } - - { ruby: 2.4.9, gemfile: rails60 } - - { ruby: 2.4.9, gemfile: rails60_boc } - - { ruby: 2.4.9, gemfile: rails60_haml } - - { ruby: 2.5.8, gemfile: rails42 } - - { ruby: 2.5.8, gemfile: rails42_boc } - - { ruby: 2.5.8, gemfile: rails42_haml } - - { ruby: 2.6.6, gemfile: rails42 } - - { ruby: 2.6.6, gemfile: rails42_boc } - - { ruby: 2.6.6, gemfile: rails42_haml } - - { ruby: 2.7.2, gemfile: rails42 } - - { ruby: 2.7.2, gemfile: rails42_boc } - - { ruby: 2.7.2, gemfile: rails42_haml } - - { ruby: ruby-head, gemfile: rails42 } - - { ruby: ruby-head, gemfile: rails42_boc } - - { ruby: ruby-head, gemfile: rails42_haml } - - { ruby: truffleruby-head, gemfile: rails42_boc } - - { ruby: truffleruby-head, gemfile: rails50_boc } - - { ruby: truffleruby-head, gemfile: rails51_boc } - - { ruby: truffleruby-head, gemfile: rails52_boc } - - { ruby: truffleruby-head, gemfile: rails60_boc } - - { ruby: truffleruby-head, gemfile: rack_boc } + - { ruby: 2.2, gemfile: rails60 } + - { ruby: 2.2, gemfile: rails60_boc } + - { ruby: 2.2, gemfile: rails60_haml } + - { ruby: 2.3, gemfile: rails42 } + - { ruby: 2.3, gemfile: rails42_boc } + - { ruby: 2.3, gemfile: rails42_haml } + - { ruby: 2.3, gemfile: rails60 } + - { ruby: 2.3, gemfile: rails60_boc } + - { ruby: 2.3, gemfile: rails60_haml } + - { ruby: 2.4, gemfile: rails42 } + - { ruby: 2.4, gemfile: rails42_boc } + - { ruby: 2.4, gemfile: rails42_haml } + - { ruby: 2.4, gemfile: rails60 } + - { ruby: 2.4, gemfile: rails60_boc } + - { ruby: 2.4, gemfile: rails60_haml } + - { ruby: 2.5, gemfile: rails42 } + - { ruby: 2.5, gemfile: rails42_boc } + - { ruby: 2.5, gemfile: rails42_haml } + - { ruby: 2.6, gemfile: rails42 } + - { ruby: 2.6, gemfile: rails42_boc } + - { ruby: 2.6, gemfile: rails42_haml } + - { ruby: 2.7, gemfile: rails42 } + - { ruby: 2.7, gemfile: rails42_boc } + - { ruby: 2.7, gemfile: rails42_haml } + # - { ruby: ruby-head, gemfile: rails42 } + # - { ruby: ruby-head, gemfile: rails42_boc } + # - { ruby: ruby-head, gemfile: rails42_haml } + - { ruby: truffleruby, gemfile: rails42_boc } + - { ruby: truffleruby, gemfile: rails50_boc } + - { ruby: truffleruby, gemfile: rails51_boc } + - { ruby: truffleruby, gemfile: rails52_boc } + - { ruby: truffleruby, gemfile: rails60_boc } + - { ruby: truffleruby, gemfile: rack_boc } steps: - uses: actions/checkout@v2 From f528291537978802394fe6abdbf4de71067f38c0 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 18:48:59 -0500 Subject: [PATCH 16/73] Disable pry builds for now they're failing in new CI, and Pry 0.9 is way outdated anyway. --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b0d7022..9828e897 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: ruby: - 2.2 @@ -42,7 +42,9 @@ jobs: - rails60_boc - rack - rack_boc - - pry09 + # - pry09 + # - pry10 + # - pry11 exclude: - { ruby: 2.2, gemfile: rails60 } - { ruby: 2.2, gemfile: rails60_boc } From 0b18732768da94577a5984c8097319f19bed62c1 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 18:55:03 -0500 Subject: [PATCH 17/73] Use specific gemfile for caching bundle --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9828e897..6faa4bc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: - uses: actions/cache@v2 with: path: vendor/bundle - key: ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles('gemfiles/*.gemfile') }} + key: ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }} restore-keys: | ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} ${{ runner.os }}-ruby-${{ matrix.ruby }} From a8a22449c6180a700a01a8ed0efc997b6a3789d4 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 19:14:26 -0500 Subject: [PATCH 18/73] Use truffleruby head Since the latest release apparently doesn't work. --- .github/workflows/ci.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6faa4bc1..6dabdc8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,7 @@ on: jobs: test: - runs-on: ubuntu-latest - strategy: fail-fast: false matrix: @@ -22,7 +20,7 @@ jobs: - 2.6 - 2.7 # - ruby-head - - truffleruby + - truffleruby-head gemfile: # These are located in the gemfiles/ folder - rails42 @@ -73,14 +71,15 @@ jobs: # - { ruby: ruby-head, gemfile: rails42 } # - { ruby: ruby-head, gemfile: rails42_boc } # - { ruby: ruby-head, gemfile: rails42_haml } - - { ruby: truffleruby, gemfile: rails42_boc } - - { ruby: truffleruby, gemfile: rails50_boc } - - { ruby: truffleruby, gemfile: rails51_boc } - - { ruby: truffleruby, gemfile: rails52_boc } - - { ruby: truffleruby, gemfile: rails60_boc } - - { ruby: truffleruby, gemfile: rack_boc } + - { ruby: truffleruby-head, gemfile: rails42_boc } + - { ruby: truffleruby-head, gemfile: rails50_boc } + - { ruby: truffleruby-head, gemfile: rails51_boc } + - { ruby: truffleruby-head, gemfile: rails52_boc } + - { ruby: truffleruby-head, gemfile: rails60_boc } + - { ruby: truffleruby-head, gemfile: rack_boc } steps: + - uses: actions/checkout@v2 - name: Set up Ruby From 0f76489abe83025df45ec4da8af6249e9eadd953 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 19:48:04 -0500 Subject: [PATCH 19/73] Remove truffleruby --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dabdc8b..883afffb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - 2.6 - 2.7 # - ruby-head - - truffleruby-head + # - truffleruby-head gemfile: # These are located in the gemfiles/ folder - rails42 From f8c07fff8710f32e4eb90953f32090fd9fba58a1 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 19:48:53 -0500 Subject: [PATCH 20/73] Improve caching by using branch name --- .github/workflows/ci.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 883afffb..567fbd7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,16 +90,15 @@ jobs: - uses: actions/cache@v2 with: path: vendor/bundle - key: ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }} + key: ${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }} restore-keys: | - ${{ runner.os }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} - ${{ runner.os }}-ruby-${{ matrix.ruby }} - - - name: Configure bundler - run: bundle config path vendor/bundle + ${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} + ${{ runner.os }}-branch-master-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} - name: Bundle install - run: bundle install --jobs 4 --retry 3 + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile From c52a06a005a5897f62212a4d02dc2f9f4ae7a224 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 19:59:48 -0500 Subject: [PATCH 21/73] Report completion to Coveralls --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 567fbd7d..e1f0726e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,3 +106,15 @@ jobs: run: bundle exec rspec -f doc --color env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile + + + finish: + needs: test + runs-on: ubuntu-latest + steps: + + - name: Report completion to Coveralls + uses: coverallsapp/github-action@v1 + with: + github-token: ${{ secrets.github_token }} + parallel-finished: true From caa2cc9e2182f784ed3b9d78a763ab43c3499b65 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 20:10:14 -0500 Subject: [PATCH 22/73] Trying to get the cache working --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1f0726e..e8b6b77c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,11 +89,11 @@ jobs: - uses: actions/cache@v2 with: - path: vendor/bundle - key: ${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }} + path: gemfiles/vendor/bundle + key: v3-${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }}-${{ hashFiles(format('gemfiles/{0}.gemfile', matrix.gemfile)) }} restore-keys: | - ${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} - ${{ runner.os }}-branch-master-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} + v3-${{ runner.os }}-branch-${{ github.ref }}-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} + v3-${{ runner.os }}-branch-master-ruby-${{ matrix.ruby }}-gemfile-${{ matrix.gemfile }} - name: Bundle install run: | From 773edc5f1de973135a28d405e69ca990b35af3ee Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 3 Nov 2020 20:45:14 -0500 Subject: [PATCH 23/73] Use coveralls for each job --- .github/workflows/ci.yml | 9 ++++++++- gemfiles/pry010.gemfile | 3 ++- gemfiles/pry011.gemfile | 3 ++- gemfiles/pry09.gemfile | 3 ++- gemfiles/rack.gemfile | 3 ++- gemfiles/rack_boc.gemfile | 3 ++- gemfiles/rails42.gemfile | 3 ++- gemfiles/rails42_boc.gemfile | 3 ++- gemfiles/rails42_haml.gemfile | 3 ++- gemfiles/rails50.gemfile | 3 ++- gemfiles/rails50_boc.gemfile | 3 ++- gemfiles/rails50_haml.gemfile | 3 ++- gemfiles/rails51.gemfile | 3 ++- gemfiles/rails51_boc.gemfile | 3 ++- gemfiles/rails51_haml.gemfile | 3 ++- gemfiles/rails52.gemfile | 3 ++- gemfiles/rails52_boc.gemfile | 3 ++- gemfiles/rails52_haml.gemfile | 3 ++- gemfiles/rails60.gemfile | 3 ++- gemfiles/rails60_boc.gemfile | 3 ++- gemfiles/rails60_haml.gemfile | 3 ++- spec/spec_helper.rb | 28 +++++++++++++++------------- 22 files changed, 63 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8b6b77c..d2f0943e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,6 +107,13 @@ jobs: env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile + - name: Report to Coveralls + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.github_token }} + flag-name: test-${{ matrix.ruby }}-${{ matrix.gemfile }} + parallel: true + finish: needs: test @@ -114,7 +121,7 @@ jobs: steps: - name: Report completion to Coveralls - uses: coverallsapp/github-action@v1 + uses: coverallsapp/github-action@v1.1.2 with: github-token: ${{ secrets.github_token }} parallel-finished: true diff --git a/gemfiles/pry010.gemfile b/gemfiles/pry010.gemfile index 4503b67c..1daca580 100644 --- a/gemfiles/pry010.gemfile +++ b/gemfiles/pry010.gemfile @@ -4,6 +4,7 @@ gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0' gem "binding_of_caller" gem "pry", "~> 0.10.0" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/pry011.gemfile b/gemfiles/pry011.gemfile index 761c5918..206b89d7 100644 --- a/gemfiles/pry011.gemfile +++ b/gemfiles/pry011.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0' gem "pry", "~> 0.11.0pre" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/pry09.gemfile b/gemfiles/pry09.gemfile index db7fa6bc..130326b9 100644 --- a/gemfiles/pry09.gemfile +++ b/gemfiles/pry09.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0' gem "pry", "~> 0.9.12" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rack.gemfile b/gemfiles/rack.gemfile index 4f2bab73..b5bbff7a 100644 --- a/gemfiles/rack.gemfile +++ b/gemfiles/rack.gemfile @@ -2,6 +2,7 @@ source "https://rubygems.org" gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0' -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rack_boc.gemfile b/gemfiles/rack_boc.gemfile index 0899c028..09520d9b 100644 --- a/gemfiles/rack_boc.gemfile +++ b/gemfiles/rack_boc.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem 'rack', RUBY_VERSION < '2.2.2' ? '~> 1.6' : '~> 2.0' gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails42.gemfile b/gemfiles/rails42.gemfile index ba2e191f..caaeb8ef 100644 --- a/gemfiles/rails42.gemfile +++ b/gemfiles/rails42.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 4.2.0" gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7' gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails42_boc.gemfile b/gemfiles/rails42_boc.gemfile index 2e66ac54..c3619a6a 100644 --- a/gemfiles/rails42_boc.gemfile +++ b/gemfiles/rails42_boc.gemfile @@ -5,6 +5,7 @@ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7' gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails42_haml.gemfile b/gemfiles/rails42_haml.gemfile index a22370a6..6f656aae 100644 --- a/gemfiles/rails42_haml.gemfile +++ b/gemfiles/rails42_haml.gemfile @@ -5,6 +5,7 @@ gem 'nokogiri', RUBY_VERSION < '2.1' ? '~> 1.6.0' : '>= 1.7' gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "haml" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails50.gemfile b/gemfiles/rails50.gemfile index 7d31f08d..856109f5 100644 --- a/gemfiles/rails50.gemfile +++ b/gemfiles/rails50.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rails", "~> 5.0.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails50_boc.gemfile b/gemfiles/rails50_boc.gemfile index a7955aad..6632ab09 100644 --- a/gemfiles/rails50_boc.gemfile +++ b/gemfiles/rails50_boc.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.0.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails50_haml.gemfile b/gemfiles/rails50_haml.gemfile index 5ad597ec..c549086b 100644 --- a/gemfiles/rails50_haml.gemfile +++ b/gemfiles/rails50_haml.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.0.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "haml" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails51.gemfile b/gemfiles/rails51.gemfile index 5532febb..6b80d819 100644 --- a/gemfiles/rails51.gemfile +++ b/gemfiles/rails51.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rails", "~> 5.1.0" gem 'i18n', '< 1.5.2', require: false if RUBY_VERSION < '2.3' -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails51_boc.gemfile b/gemfiles/rails51_boc.gemfile index bfb2cc92..391459d4 100644 --- a/gemfiles/rails51_boc.gemfile +++ b/gemfiles/rails51_boc.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.1.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails51_haml.gemfile b/gemfiles/rails51_haml.gemfile index a870a7cf..4be7c4bc 100644 --- a/gemfiles/rails51_haml.gemfile +++ b/gemfiles/rails51_haml.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.1.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "haml" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails52.gemfile b/gemfiles/rails52.gemfile index 070970cd..887de07d 100644 --- a/gemfiles/rails52.gemfile +++ b/gemfiles/rails52.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rails", "~> 5.2.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails52_boc.gemfile b/gemfiles/rails52_boc.gemfile index 195e4e23..669c73fd 100644 --- a/gemfiles/rails52_boc.gemfile +++ b/gemfiles/rails52_boc.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.2.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails52_haml.gemfile b/gemfiles/rails52_haml.gemfile index dd9f0dc9..c2bb1f57 100644 --- a/gemfiles/rails52_haml.gemfile +++ b/gemfiles/rails52_haml.gemfile @@ -4,6 +4,7 @@ gem "rails", "~> 5.2.0" gem 'i18n', '< 1.5.2' if RUBY_VERSION < '2.3' gem "haml" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails60.gemfile b/gemfiles/rails60.gemfile index 55f89c5e..825f46ca 100644 --- a/gemfiles/rails60.gemfile +++ b/gemfiles/rails60.gemfile @@ -2,6 +2,7 @@ source "https://rubygems.org" gem "rails", "~> 6.0.0" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails60_boc.gemfile b/gemfiles/rails60_boc.gemfile index 190c573c..c32cb5d9 100644 --- a/gemfiles/rails60_boc.gemfile +++ b/gemfiles/rails60_boc.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rails", "~> 6.0.0" gem "binding_of_caller" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/gemfiles/rails60_haml.gemfile b/gemfiles/rails60_haml.gemfile index 84d3401a..e4f3179c 100644 --- a/gemfiles/rails60_haml.gemfile +++ b/gemfiles/rails60_haml.gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rails", "~> 6.0.0" gem "haml" -gem 'coveralls', require: false +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false gemspec path: "../" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 29e5ac18..c4544d78 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,19 +2,21 @@ ENV["EDITOR"] = nil -# Ruby 2.4.0 and 2.4.1 has a bug with its Coverage module that causes segfaults. -# https://bugs.ruby-lang.org/issues/13305 -# 2.4.2 should include this patch. -if ENV['CI'] - unless RUBY_VERSION == '2.4.0' || RUBY_VERSION == '2.4.1' - require 'coveralls' - Coveralls.wear! do - add_filter 'spec/' - end - end -else - require 'simplecov' - SimpleCov.start +require 'simplecov' +require 'simplecov-lcov' + +SimpleCov::Formatter::LcovFormatter.config do |c| + c.report_with_single_file = true + c.single_report_path = 'coverage/lcov.info' +end +SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new( + [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter, + ] +) +SimpleCov.start do + add_filter 'spec/' end require 'bundler/setup' From db589f2463d274f54a003442a11858bd6dc546af Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 09:14:44 -0500 Subject: [PATCH 24/73] Fix simplecov-lcov incompatible with older simplecov (which is required to support Ruby < 2.4) --- spec/spec_helper.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c4544d78..9828c3f3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,6 +5,16 @@ require 'simplecov' require 'simplecov-lcov' +# Fix incompatibility of simplecov-lcov with older versions of simplecov that are not expresses in its gemspec. +# https://github.com/fortissimo1997/simplecov-lcov/pull/25 +if !SimpleCov.respond_to?(:branch_coverage) + module SimpleCov + def self.branch_coverage? + false + end + end +end + SimpleCov::Formatter::LcovFormatter.config do |c| c.report_with_single_file = true c.single_report_path = 'coverage/lcov.info' From 298a89bce0a54b94eae64e56b318fa90e9dcc8e7 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 09:37:50 -0500 Subject: [PATCH 25/73] Update build status badge --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d428c13d..5847a86d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -[![Build Status](https://travis-ci.org/BetterErrors/better_errors.svg)](https://travis-ci.org/BetterErrors/better_errors) +[![Build Status](https://github.com/BetterErrors/better_errors/workflows/CI/badge.svg?event=push&branch=master)](https://github.com/BetterErrors/better_errors/actions?query=branch%3Amaster) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6bc3e7d6118d47e6959b16690b815909)](https://www.codacy.com/app/BetterErrors/better_errors?utm_source=github.com&utm_medium=referral&utm_content=BetterErrors/better_errors&utm_campaign=Badge_Grade) -[![Coverage](https://coveralls.io/repos/github/BetterErrors/better_errors/badge.svg?branch=master)](https://coveralls.io/github/BetterErrors/better_errors?branch=master) +[![Test Coverage](https://coveralls.io/repos/github/BetterErrors/better_errors/badge.svg?branch=master)](https://coveralls.io/github/BetterErrors/better_errors?branch=master) [![Gem Version](https://img.shields.io/gem/v/better_errors.svg)](https://rubygems.org/gems/better_errors) # Better Errors From 03b3577b2b8b0bc141b6e283d67cf06df352ca8e Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 09:52:02 -0500 Subject: [PATCH 26/73] Add cron CI builds --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2f0943e..87f5fc47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: CI on: push: branches: [ master ] + schedule: + - cron: '0 0 12,26 * *' # roughly every two weeks to run on new Ruby versions pull_request: branches: [ master ] From d38579e7a0c36771d4736681513753f6e1d945c7 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 10:49:50 -0500 Subject: [PATCH 27/73] Add gem-release for CI and set dev ruby version --- .ruby-version | 1 + Gemfile | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 .ruby-version diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..37c2961c --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.2 diff --git a/Gemfile b/Gemfile index 07cd2076..6565e7af 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,10 @@ source 'https://rubygems.org' gemspec -# gem "pry-byebug" gem 'simplecov', require: false +gem 'simplecov-lcov', require: false + +# For managing release version in CI +gem 'gem-release' + +# gem "pry-byebug" From f47ef8e0a94fa1a3ed04254ce316a2ec20a2bce4 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 11:10:22 -0500 Subject: [PATCH 28/73] Release workflow --- .github/workflows/release.yml | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..57887159 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,64 @@ +name: Release + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v2 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.7 + + - uses: actions/cache@v2 + with: + path: vendor/bundle + key: v1-${{ runner.os }}-${{ hashFiles('Gemfile', 'better_errors.gemspec') }} + restore-keys: | + v1-${{ runner.os }} + + - name: Bundle install + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: Get release version + id: get_version + run: | + version="${github_ref//refs\/tags\/v/}" + echo "${version}" + echo "::set-output name=version::${version}" + env: + github_ref: ${{ github.ref }} + + - name: Get Release + id: get_release + uses: bruceadams/get-release@v1.2.2 + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Set gem version + run: | + bundle exec gem bump better_errors --version ${{ steps.get_version.outputs.version }} --no-commit + + - name: Build gem + run: gem build better_errors.gemspec + + - name: Upload gem to Release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.get_release.outputs.upload_url }} + asset_path: ./better_errors-${{ steps.get_version.outputs.version }}.gem + asset_name: better_errors-${{ steps.get_version.outputs.version }}.gem + asset_content_type: application/octet-stream + + # TODO: if this release is on master, add a commit updating the version in master. From 95d811f794ff0c61a8782d737ec0b2c3eb319167 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 11:54:28 -0500 Subject: [PATCH 29/73] Allow CI runs to be manually started --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87f5fc47..300ea272 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,7 @@ on: - cron: '0 0 12,26 * *' # roughly every two weeks to run on new Ruby versions pull_request: branches: [ master ] + workflow_dispatch: jobs: test: From a557972d642c614b57dbd46666dbf1a97b8341d9 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 12:55:15 -0500 Subject: [PATCH 30/73] Fix passing regex to start_with? --- lib/better_errors/exception_hint.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/better_errors/exception_hint.rb b/lib/better_errors/exception_hint.rb index a873c770..61ca9935 100644 --- a/lib/better_errors/exception_hint.rb +++ b/lib/better_errors/exception_hint.rb @@ -10,7 +10,7 @@ def hint /\Aundefined method `(?[^']+)' for (?[^:]+):(?\w+)/.match(exception.message) do |match| if match[:val] == "nil" return "Something is `nil` when it probably shouldn't be." - elsif !match[:klass].start_with? /\A0x/ + elsif !match[:klass].start_with? '0x' return "`#{match[:method]}` is being called on a `#{match[:klass]}` object, "\ "which might not be the type of object you were expecting." end From 621cdd73a553909e41acf319d4000ecbfc6cdd16 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 13:00:37 -0500 Subject: [PATCH 31/73] Fix spec looking for Integer class in older Ruby --- spec/better_errors/exception_hint_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/better_errors/exception_hint_spec.rb b/spec/better_errors/exception_hint_spec.rb index 68412b4b..9654f720 100644 --- a/spec/better_errors/exception_hint_spec.rb +++ b/spec/better_errors/exception_hint_spec.rb @@ -43,8 +43,9 @@ let(:val) { 42 } it { - is_expected.to eq("`foo` is being called on a `Integer` object"\ - ", which might not be the type of object you were expecting.") + is_expected.to match( + /`foo` is being called on a `(Integer|Fixnum)` object, which might not be the type of object you were expecting./ + ) } end end From 728ccdde9d2d0c726abab0fa9efa6f0ee05984ac Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 13:46:04 -0500 Subject: [PATCH 32/73] If the user ever used the console, hide the hint --- lib/better_errors/templates/main.erb | 18 +++++++++++++++++- lib/better_errors/templates/variable_info.erb | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb index c7c8c6a8..1fe049ce 100644 --- a/lib/better_errors/templates/main.erb +++ b/lib/better_errors/templates/main.erb @@ -849,15 +849,31 @@ this.inputElement = this.container.querySelector("input"); this.outputElement = this.container.querySelector("pre"); + this.hasUsedConsole = document.cookie.split('; ').find(function(cookie) { + return cookie.startsWith('BetterErrors-has-used-console='); + }); + if (this.hasUsedConsole) { + this.hideConsoleHint(); + } + var self = this; this.inputElement.onkeydown = function(ev) { self.onKeyDown(ev); + if (!self.hasUsedConsole) { + self.hideConsoleHint(); + self.hasUsedConsole = true; + document.cookie = "BetterErrors-has-used-console=true;path=/;max-age=31536000;samesite" + } }; this.setPrompt(">>"); REPL.all[this.index] = this; - } + }; + + REPL.prototype.hideConsoleHint = function() { + document.querySelector('#live-shell-hint').style["display"] = "none"; + }; REPL.prototype.focus = function() { this.inputElement.focus(); diff --git a/lib/better_errors/templates/variable_info.erb b/lib/better_errors/templates/variable_info.erb index 24f21cd5..8b9c61bd 100644 --- a/lib/better_errors/templates/variable_info.erb +++ b/lib/better_errors/templates/variable_info.erb @@ -25,7 +25,7 @@ <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
+
This is a live shell. Type in here.
From a5293dfdbd5e414e27cf19d1a69f5500f033b744 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 13:46:19 -0500 Subject: [PATCH 33/73] Remove divider line between variable types --- lib/better_errors/templates/main.erb | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb index 1fe049ce..5da0c530 100644 --- a/lib/better_errors/templates/main.erb +++ b/lib/better_errors/templates/main.erb @@ -611,17 +611,6 @@ margin: 10px 0; } - .sub:before { - content: ''; - display: block; - width: 100%; - height: 4px; - - border-radius: 2px; - background: rgba(0, 150, 200, 0.05); - box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04), inset 2px 2px 2px rgba(0, 0, 0, 0.07); - } - .sub h3 { color: #39a; font-size: 1.1em; From 4f95f3bd8abdb8fd3cce346f26da3d2fcdc74030 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Sat, 31 Oct 2020 11:21:30 -0400 Subject: [PATCH 34/73] Refactor to Editor module and call pattern Adding support for BETTER_ERRORS_EDITOR env var. --- lib/better_errors.rb | 49 +++++++------------- lib/better_errors/editor.rb | 81 +++++++++++++++++++++++++++++++++ lib/better_errors/error_page.rb | 2 +- spec/better_errors_spec.rb | 30 ++++++------ spec/spec_helper.rb | 1 + 5 files changed, 114 insertions(+), 49 deletions(-) create mode 100644 lib/better_errors/editor.rb diff --git a/lib/better_errors.rb b/lib/better_errors.rb index 8cd6b7ec..169c1171 100644 --- a/lib/better_errors.rb +++ b/lib/better_errors.rb @@ -11,20 +11,9 @@ require "better_errors/raised_exception" require "better_errors/repl" require "better_errors/stack_frame" +require "better_errors/editor" module BetterErrors - POSSIBLE_EDITOR_PRESETS = [ - { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" }, - { symbols: [:macvim, :mvim], sniff: /vim/i, url: proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" } }, - { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" }, - { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" }, - { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" }, - { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" }, - { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" }, - { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" }, - { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" }, - ] - class << self # The path to the root of the application. Better Errors uses this property # to determine if a file in a backtrace should be considered an application @@ -64,17 +53,18 @@ class << self @maximum_variable_inspect_size = 100_000 @ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response'] - # Returns a proc, which when called with a filename and line number argument, + # Returns an object which responds to #url, which when called with + # a filename and line number argument, # returns a URL to open the filename and line in the selected editor. # # Generates TextMate URLs by default. # - # BetterErrors.editor["/some/file", 123] + # BetterErrors.editor.url("/some/file", 123) # # => txmt://open?url=file:///some/file&line=123 # # @return [Proc] def self.editor - @editor + @editor ||= default_editor end # Configures how Better Errors generates open-in-editor URLs. @@ -115,20 +105,17 @@ def self.editor # @param [Proc] proc # def self.editor=(editor) - POSSIBLE_EDITOR_PRESETS.each do |config| - if config[:symbols].include?(editor) - return self.editor = config[:url] - end - end - - if editor.is_a? String - self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } } + if editor.respond_to? :url + @editor = editor + elsif editor.is_a? Symbol + @editor = Editor.for_symbol(editor) + raise(ArgumentError, "Symbol #{editor} is not a symbol in the list of supported errors.") unless editor + elsif editor.is_a? String + @editor = Editor.for_formatting_string(editor) + elsif editor.respond_to? :call + @editor = Editor.for_proc(editor) else - if editor.respond_to? :call - @editor = editor - else - raise TypeError, "Expected editor to be a valid editor key, a format string or a callable." - end + raise ArgumentError, "Expected editor to be a valid editor key, a format string or a callable." end end @@ -145,12 +132,8 @@ def self.use_pry! # # @return [Symbol] def self.default_editor - POSSIBLE_EDITOR_PRESETS.detect(-> { {} }) { |config| - ENV["EDITOR"] =~ config[:sniff] - }[:url] || :textmate + Editor.default_editor end - - BetterErrors.editor = default_editor end begin diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb new file mode 100644 index 00000000..c6022322 --- /dev/null +++ b/lib/better_errors/editor.rb @@ -0,0 +1,81 @@ +require "uri" + +module BetterErrors + module Editor + KNOWN_EDITORS = [ + { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" }, + { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" }, + { symbols: [:idea], sniff: /idea/i, url: "idea://open?file=%{file}&line=%{line}" }, + { symbols: [:macvim, :mvim], sniff: /vim/i, url: "mvim://open?url=file://%{file_unencoded}&line=%{line}" }, + { symbols: [:rubymine], sniff: /mine/i, url: "x-mine://open?file=%{file}&line=%{line}" }, + { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" }, + { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" }, + { symbols: [:vscode, :code], sniff: /code/i, url: "vscode://file/%{file}:%{line}" }, + { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" }, + ] + + class UsingFormattingString + def initialize(url_formatting_string) + @url_formatting_string = url_formatting_string + end + + def url(file, line) + url_formatting_string % { file: URI.encode_www_form_component(file), file_unencoded: file, line: line } + end + + private + + attr_reader :url_formatting_string + end + + class UsingProc + def initialize(url_proc) + @url_proc = url_proc + end + + def url(file, line) + url_proc.call(file, line) + end + + private + + attr_reader :url_proc + end + + def self.for_formatting_string(formatting_string) + UsingFormattingString.new(formatting_string) + end + + def self.for_proc(url_proc) + UsingProc.new(url_proc) + end + + def self.for_symbol(symbol) + KNOWN_EDITORS.each do |preset| + return for_formatting_string(preset[:url]) if preset[:symbols].include?(symbol) + end + end + + # Automatically sniffs a default editor preset based on the EDITOR + # environment variable. + # + # @return [Symbol] + def self.default_editor + editor_command = ENV["EDITOR"] || ENV["BETTER_ERRORS_EDITOR"] + if editor_command + editor = editor_from_command(editor_command) + return editor if editor + + puts "Since EDITOR or BETTER_ERRORS_EDITOR environment variable are not recognized, using Textmate by default." + else + puts "Since there is no EDITOR or BETTER_ERRORS_EDITOR environment variable, using Textmate by default." + end + for_symbol(:textmate) + end + + def self.editor_from_command(editor_command) + env_preset = KNOWN_EDITORS.find { |preset| editor_command =~ preset[:sniff] } + for_formatting_string(env_preset[:url]) if env_preset + end + end +end diff --git a/lib/better_errors/error_page.rb b/lib/better_errors/error_page.rb index 0eb1081d..1e44bd6e 100644 --- a/lib/better_errors/error_page.rb +++ b/lib/better_errors/error_page.rb @@ -94,7 +94,7 @@ def first_frame private def editor_url(frame) - BetterErrors.editor[frame.filename, frame.line] + BetterErrors.editor.url(frame.filename, frame.line) end def rack_session diff --git a/spec/better_errors_spec.rb b/spec/better_errors_spec.rb index 9d796105..2ab2a486 100644 --- a/spec/better_errors_spec.rb +++ b/spec/better_errors_spec.rb @@ -3,45 +3,45 @@ describe BetterErrors do context ".editor" do it "defaults to textmate" do - expect(subject.editor["foo.rb", 123]).to eq("txmt://open?url=file://foo.rb&line=123") + expect(subject.editor.url("foo.rb", 123)).to eq("txmt://open?url=file://foo.rb&line=123") end it "url escapes the filename" do - expect(subject.editor["&.rb", 0]).to eq("txmt://open?url=file://%26.rb&line=0") + expect(subject.editor.url("&.rb", 0)).to eq("txmt://open?url=file://%26.rb&line=0") end [:emacs, :emacsclient].each do |editor| it "uses emacs:// scheme when set to #{editor.inspect}" do subject.editor = editor - expect(subject.editor[]).to start_with "emacs://" + expect(subject.editor.url("file", 42)).to start_with "emacs://" end end [:macvim, :mvim].each do |editor| it "uses mvim:// scheme when set to #{editor.inspect}" do subject.editor = editor - expect(subject.editor[]).to start_with "mvim://" + expect(subject.editor.url("file", 42)).to start_with "mvim://" end end [:sublime, :subl, :st].each do |editor| it "uses subl:// scheme when set to #{editor.inspect}" do subject.editor = editor - expect(subject.editor[]).to start_with "subl://" + expect(subject.editor.url("file", 42)).to start_with "subl://" end end [:textmate, :txmt, :tm].each do |editor| it "uses txmt:// scheme when set to #{editor.inspect}" do subject.editor = editor - expect(subject.editor[]).to start_with "txmt://" + expect(subject.editor.url("file", 42)).to start_with "txmt://" end end [:atom].each do |editor| it "uses atom:// scheme when set to #{editor.inspect}" do subject.editor = editor - expect(subject.editor[]).to start_with "atom://" + expect(subject.editor.url("file", 42)).to start_with "atom://" end end @@ -49,7 +49,7 @@ it "uses emacs:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "emacs://" + expect(subject.editor.url("file", 42)).to start_with "emacs://" end end @@ -57,7 +57,7 @@ it "uses mvim:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "mvim://" + expect(subject.editor.url("file", 42)).to start_with "mvim://" end end @@ -65,7 +65,7 @@ it "uses subl:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "subl://" + expect(subject.editor.url("file", 42)).to start_with "subl://" end end @@ -73,7 +73,7 @@ it "uses txmt:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "txmt://" + expect(subject.editor.url("file", 42)).to start_with "txmt://" end end @@ -82,7 +82,7 @@ it "uses atom:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "atom://" + expect(subject.editor.url("file", 42)).to start_with "atom://" end end @@ -90,7 +90,7 @@ it "uses x-mine:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "x-mine://" + expect(subject.editor.url("file", 42)).to start_with "x-mine://" end end @@ -98,7 +98,7 @@ it "uses idea:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "idea://" + expect(subject.editor.url("file", 42)).to start_with "idea://" end end @@ -106,7 +106,7 @@ it "uses vscode:// scheme when EDITOR=#{editor}" do ENV["EDITOR"] = editor subject.editor = subject.default_editor - expect(subject.editor[]).to start_with "vscode://" + expect(subject.editor.url("file", 42)).to start_with "vscode://" end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9828c3f3..31d351ab 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,7 @@ $: << File.expand_path("../../lib", __FILE__) ENV["EDITOR"] = nil +ENV["BETTER_ERRORS"] = nil require 'simplecov' require 'simplecov-lcov' From c907709a723791f3d5fc129666d51c406afde4dc Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 14:14:14 -0500 Subject: [PATCH 35/73] Support for BETTER_ERRORS_EDITOR_URL --- lib/better_errors/editor.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb index c6022322..30ce6050 100644 --- a/lib/better_errors/editor.rb +++ b/lib/better_errors/editor.rb @@ -61,6 +61,12 @@ def self.for_symbol(symbol) # # @return [Symbol] def self.default_editor + editor_from_environment_formatting_string || + editor_from_environment_editor || + for_symbol(:textmate) + end + + def self.editor_from_environment_editor editor_command = ENV["EDITOR"] || ENV["BETTER_ERRORS_EDITOR"] if editor_command editor = editor_from_command(editor_command) @@ -70,12 +76,17 @@ def self.default_editor else puts "Since there is no EDITOR or BETTER_ERRORS_EDITOR environment variable, using Textmate by default." end - for_symbol(:textmate) end def self.editor_from_command(editor_command) env_preset = KNOWN_EDITORS.find { |preset| editor_command =~ preset[:sniff] } for_formatting_string(env_preset[:url]) if env_preset end + + def self.editor_from_environment_formatting_string + return unless ENV['BETTER_ERRORS_EDITOR_URL'] + + for_formatting_string(ENV['BETTER_ERRORS_EDITOR_URL']) + end end end From 2b520a0fa5564b69a28c7415a7deacd50553c2d3 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:10:01 -0500 Subject: [PATCH 36/73] Remove new undocumented behavior of passing an object that responds to #url. --- lib/better_errors.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/better_errors.rb b/lib/better_errors.rb index 169c1171..af46bdd5 100644 --- a/lib/better_errors.rb +++ b/lib/better_errors.rb @@ -105,9 +105,7 @@ def self.editor # @param [Proc] proc # def self.editor=(editor) - if editor.respond_to? :url - @editor = editor - elsif editor.is_a? Symbol + if editor.is_a? Symbol @editor = Editor.for_symbol(editor) raise(ArgumentError, "Symbol #{editor} is not a symbol in the list of supported errors.") unless editor elsif editor.is_a? String From 5931137088b0d688745462ca1a9c1553233ef4c6 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:10:32 -0500 Subject: [PATCH 37/73] Specs for Editor module --- lib/better_errors/editor.rb | 17 ++- spec/better_errors/editor_spec.rb | 233 ++++++++++++++++++++++++++++++ spec/better_errors_spec.rb | 129 +++++------------ 3 files changed, 276 insertions(+), 103 deletions(-) create mode 100644 spec/better_errors/editor_spec.rb diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb index 30ce6050..0e998637 100644 --- a/lib/better_errors/editor.rb +++ b/lib/better_errors/editor.rb @@ -56,8 +56,8 @@ def self.for_symbol(symbol) end end - # Automatically sniffs a default editor preset based on the EDITOR - # environment variable. + # Automatically sniffs a default editor preset based on + # environment variables. # # @return [Symbol] def self.default_editor @@ -67,12 +67,15 @@ def self.default_editor end def self.editor_from_environment_editor - editor_command = ENV["EDITOR"] || ENV["BETTER_ERRORS_EDITOR"] - if editor_command - editor = editor_from_command(editor_command) + if ENV["BETTER_ERRORS_EDITOR"] + editor = editor_from_command(ENV["BETTER_ERRORS_EDITOR"]) return editor if editor - - puts "Since EDITOR or BETTER_ERRORS_EDITOR environment variable are not recognized, using Textmate by default." + puts "BETTER_ERRORS_EDITOR environment variable is not recognized as a supported Better Errors editor." + end + if ENV["EDITOR"] + editor = editor_from_command(ENV["EDITOR"]) + return editor if editor + puts "EDITOR environment variable is not recognized as a supported Better Errors editor. Using TextMate by default." else puts "Since there is no EDITOR or BETTER_ERRORS_EDITOR environment variable, using Textmate by default." end diff --git a/spec/better_errors/editor_spec.rb b/spec/better_errors/editor_spec.rb new file mode 100644 index 00000000..efc73608 --- /dev/null +++ b/spec/better_errors/editor_spec.rb @@ -0,0 +1,233 @@ +require "spec_helper" + +RSpec.describe BetterErrors::Editor do + describe ".for_formatting_string" do + it "returns an object that reponds to #url" do + editor = described_class.for_formatting_string("custom://%{file}:%{file_unencoded}:%{line}") + expect(editor.url("/path&file", 42)).to eq("custom://%2Fpath%26file:/path&file:42") + end + end + + describe ".for_proc" do + it "returns an object that responds to #url, which calls the proc" do + editor = described_class.for_proc(proc { |file, line| "result" } ) + expect(editor.url("foo", 42)).to eq("result") + end + end + + describe ".for_symbol" do + subject { described_class.for_symbol(symbol) } + + [:atom].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses atom:// scheme" do + expect(subject.url("file", 42)).to start_with("atom://") + end + end + end + + [:emacs, :emacsclient].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + it "uses emacs:// scheme" do + expect(subject.url("file", 42)).to start_with("emacs://") + end + end + end + + [:macvim, :mvim].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses mvim:// scheme" do + expect(subject.url("file", 42)).to start_with("mvim://") + end + end + end + + [:sublime, :subl, :st].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses subl:// scheme" do + expect(subject.url("file", 42)).to start_with("subl://") + end + end + end + + [:textmate, :txmt, :tm].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses txmt:// scheme" do + expect(subject.url("file", 42)).to start_with("txmt://") + end + end + end + end + + describe ".default_editor" do + subject(:default_editor) { described_class.default_editor } + before do + ENV['BETTER_ERRORS_EDITOR_URL'] = nil + ENV['BETTER_ERRORS_EDITOR'] = nil + ENV['EDITOR'] = nil + end + + it "returns an object that responds to #url" do + expect(default_editor.url("foo", 123)).to match(/foo/) + end + + context "when $BETTER_ERRORS_EDITOR_URL is set" do + before do + ENV['BETTER_ERRORS_EDITOR_URL'] = "custom://%{file}:%{file_unencoded}:%{line}" + end + + it "uses the value as a formatting string to build the editor URL" do + expect(default_editor.url("/path&file", 42)).to eq("custom://%2Fpath%26file:/path&file:42") + end + end + + context "when $BETTER_ERRORS_EDITOR is set to one of the preset commands" do + before do + ENV['BETTER_ERRORS_EDITOR'] = "subl" + end + + it "returns an object that builds URLs for the corresponding editor" do + expect(default_editor.url("foo", 123)).to start_with('subl://') + end + end + + context "when $EDITOR is set to one of the preset commands" do + before do + ENV['EDITOR'] = "subl" + end + + it "returns an object that builds URLs for the corresponding editor" do + expect(default_editor.url("foo", 123)).to start_with('subl://') + end + + context "when $BETTER_ERRORS_EDITOR is set to one of the preset commands" do + before do + ENV['BETTER_ERRORS_EDITOR'] = "emacs" + end + + it "returns an object that builds URLs for that editor instead" do + expect(default_editor.url("foo", 123)).to start_with('emacs://') + end + end + + context "when $BETTER_ERRORS_EDITOR is set to an unrecognized command" do + before do + ENV['BETTER_ERRORS_EDITOR'] = "fubarcmd" + end + + it "returns an object that builds URLs for the $EDITOR instead" do + expect(default_editor.url("foo", 123)).to start_with('subl://') + end + end + end + + context "when $EDITOR is set to an unrecognized command" do + before do + ENV['EDITOR'] = "fubarcmd" + end + + it "returns an object that builds URLs for TextMate" do + expect(default_editor.url("foo", 123)).to start_with('txmt://') + end + end + + context "when $EDITOR and $BETTER_ERRORS_EDITOR are not set" do + it "returns an object that builds URLs for TextMate" do + expect(default_editor.url("foo", 123)).to start_with('txmt://') + end + end + end + + describe ".editor_from_command" do + subject { described_class.editor_from_command(command_line) } + + ["atom -w", "/usr/bin/atom -w"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses atom:// scheme" do + expect(subject.url("file", 42)).to start_with("atom://") + end + end + end + + ["emacsclient", "/usr/local/bin/emacsclient"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses emacs:// scheme" do + expect(subject.url("file", 42)).to start_with("emacs://") + end + end + end + + ["idea"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses idea:// scheme" do + expect(subject.url("file", 42)).to start_with("idea://") + end + end + end + + ["mate -w", "/usr/bin/mate -w"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses txmt:// scheme" do + expect(subject.url("file", 42)).to start_with("txmt://") + end + end + end + + ["mine"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses x-mine:// scheme" do + expect(subject.url("file", 42)).to start_with("x-mine://") + end + end + end + + ["mvim -f", "/usr/local/bin/mvim -f"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses mvim:// scheme" do + expect(subject.url("file", 42)).to start_with("mvim://") + end + end + end + + ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses subl:// scheme" do + expect(subject.url("file", 42)).to start_with("subl://") + end + end + end + + ["vscode", "code"].each do |command| + context "when editor command is '#{command}'" do + let(:command_line) { command } + + it "uses vscode:// scheme" do + expect(subject.url("file", 42)).to start_with("vscode://") + end + end + end + end +end diff --git a/spec/better_errors_spec.rb b/spec/better_errors_spec.rb index 2ab2a486..0b5b6604 100644 --- a/spec/better_errors_spec.rb +++ b/spec/better_errors_spec.rb @@ -1,112 +1,49 @@ require "spec_helper" -describe BetterErrors do - context ".editor" do - it "defaults to textmate" do - expect(subject.editor.url("foo.rb", 123)).to eq("txmt://open?url=file://foo.rb&line=123") - end - - it "url escapes the filename" do - expect(subject.editor.url("&.rb", 0)).to eq("txmt://open?url=file://%26.rb&line=0") - end - - [:emacs, :emacsclient].each do |editor| - it "uses emacs:// scheme when set to #{editor.inspect}" do - subject.editor = editor - expect(subject.editor.url("file", 42)).to start_with "emacs://" - end - end - - [:macvim, :mvim].each do |editor| - it "uses mvim:// scheme when set to #{editor.inspect}" do - subject.editor = editor - expect(subject.editor.url("file", 42)).to start_with "mvim://" - end - end - - [:sublime, :subl, :st].each do |editor| - it "uses subl:// scheme when set to #{editor.inspect}" do - subject.editor = editor - expect(subject.editor.url("file", 42)).to start_with "subl://" - end - end - - [:textmate, :txmt, :tm].each do |editor| - it "uses txmt:// scheme when set to #{editor.inspect}" do - subject.editor = editor - expect(subject.editor.url("file", 42)).to start_with "txmt://" - end - end - - [:atom].each do |editor| - it "uses atom:// scheme when set to #{editor.inspect}" do - subject.editor = editor - expect(subject.editor.url("file", 42)).to start_with "atom://" - end - end - - ["emacsclient", "/usr/local/bin/emacsclient"].each do |editor| - it "uses emacs:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "emacs://" +RSpec.describe BetterErrors do + describe ".editor" do + context "when set to a specific value" do + before do + allow(BetterErrors::Editor).to receive(:for_symbol).and_return(:editor_from_symbol) + allow(BetterErrors::Editor).to receive(:for_formatting_string).and_return(:editor_from_formatting_string) + allow(BetterErrors::Editor).to receive(:for_proc).and_return(:editor_from_proc) end - end - ["mvim -f", "/usr/local/bin/mvim -f"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "mvim://" + context "when the value is a string" do + it "uses BetterErrors::Editor.for_formatting_string to set the value" do + subject.editor = "thing://%{file}" + expect(BetterErrors::Editor).to have_received(:for_formatting_string).with("thing://%{file}") + expect(subject.editor).to eq(:editor_from_formatting_string) + end end - end - ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor| - it "uses subl:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "subl://" + context "when the value is a Proc" do + it "uses BetterErrors::Editor.for_proc to set the value" do + my_proc = proc { "thing" } + subject.editor = my_proc + expect(BetterErrors::Editor).to have_received(:for_proc).with(my_proc) + expect(subject.editor).to eq(:editor_from_proc) + end end - end - ["mate -w", "/usr/bin/mate -w"].each do |editor| - it "uses txmt:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "txmt://" + context "when the value is a symbol" do + it "uses BetterErrors::Editor.for_symbol to set the value" do + subject.editor = :subl + expect(BetterErrors::Editor).to have_received(:for_symbol).with(:subl) + expect(subject.editor).to eq(:editor_from_symbol) + end end end - - ["atom -w", "/usr/bin/atom -w"].each do |editor| - it "uses atom:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "atom://" + context "when no value has been set" do + before do + BetterErrors.instance_variable_set('@editor', nil) + allow(BetterErrors::Editor).to receive(:default_editor).and_return(:default_editor) end - end - - ["mine"].each do |editor| - it "uses x-mine:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "x-mine://" - end - end - - ["idea"].each do |editor| - it "uses idea:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "idea://" - end - end - ["vscode", "code"].each do |editor| - it "uses vscode:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - expect(subject.editor.url("file", 42)).to start_with "vscode://" + it "uses BetterErrors::Editor.default_editor to set the default value" do + expect(subject.editor).to eq(:default_editor) + expect(BetterErrors::Editor).to have_received(:default_editor) end end end From b95d3c334d749a94f162fba1b68c0b9e0f68aa4f Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:14:38 -0500 Subject: [PATCH 38/73] Create instances of Editor --- lib/better_errors/editor.rb | 48 +++++++++++++------------------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb index 0e998637..cc8bf383 100644 --- a/lib/better_errors/editor.rb +++ b/lib/better_errors/editor.rb @@ -1,7 +1,7 @@ require "uri" module BetterErrors - module Editor + class Editor KNOWN_EDITORS = [ { symbols: [:atom], sniff: /atom/i, url: "atom://core/open/file?filename=%{file}&line=%{line}" }, { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" }, @@ -14,40 +14,14 @@ module Editor { symbols: [:vscodium, :codium], sniff: /codium/i, url: "vscodium://file/%{file}:%{line}" }, ] - class UsingFormattingString - def initialize(url_formatting_string) - @url_formatting_string = url_formatting_string - end - - def url(file, line) - url_formatting_string % { file: URI.encode_www_form_component(file), file_unencoded: file, line: line } - end - - private - - attr_reader :url_formatting_string - end - - class UsingProc - def initialize(url_proc) - @url_proc = url_proc - end - - def url(file, line) - url_proc.call(file, line) - end - - private - - attr_reader :url_proc - end - def self.for_formatting_string(formatting_string) - UsingFormattingString.new(formatting_string) + new proc { |file, line| + formatting_string % { file: URI.encode_www_form_component(file), file_unencoded: file, line: line } + } end def self.for_proc(url_proc) - UsingProc.new(url_proc) + new url_proc end def self.for_symbol(symbol) @@ -91,5 +65,17 @@ def self.editor_from_environment_formatting_string for_formatting_string(ENV['BETTER_ERRORS_EDITOR_URL']) end + + def initialize(url_proc) + @url_proc = url_proc + end + + def url(file, line) + url_proc.call(file, line) + end + + private + + attr_reader :url_proc end end From 6591cf998872940ae64086444aa59be30f1cbe9c Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:16:47 -0500 Subject: [PATCH 39/73] Rename method and reorder --- lib/better_errors/editor.rb | 14 ++-- spec/better_errors/editor_spec.rb | 106 +++++++++++++++--------------- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb index cc8bf383..06df7f4d 100644 --- a/lib/better_errors/editor.rb +++ b/lib/better_errors/editor.rb @@ -24,12 +24,6 @@ def self.for_proc(url_proc) new url_proc end - def self.for_symbol(symbol) - KNOWN_EDITORS.each do |preset| - return for_formatting_string(preset[:url]) if preset[:symbols].include?(symbol) - end - end - # Automatically sniffs a default editor preset based on # environment variables. # @@ -37,7 +31,7 @@ def self.for_symbol(symbol) def self.default_editor editor_from_environment_formatting_string || editor_from_environment_editor || - for_symbol(:textmate) + editor_from_symbol(:textmate) end def self.editor_from_environment_editor @@ -66,6 +60,12 @@ def self.editor_from_environment_formatting_string for_formatting_string(ENV['BETTER_ERRORS_EDITOR_URL']) end + def self.editor_from_symbol(symbol) + KNOWN_EDITORS.each do |preset| + return for_formatting_string(preset[:url]) if preset[:symbols].include?(symbol) + end + end + def initialize(url_proc) @url_proc = url_proc end diff --git a/spec/better_errors/editor_spec.rb b/spec/better_errors/editor_spec.rb index efc73608..033c05d5 100644 --- a/spec/better_errors/editor_spec.rb +++ b/spec/better_errors/editor_spec.rb @@ -15,59 +15,6 @@ end end - describe ".for_symbol" do - subject { described_class.for_symbol(symbol) } - - [:atom].each do |symbol| - context "when symbol is '#{symbol}'" do - let(:symbol) { symbol } - - it "uses atom:// scheme" do - expect(subject.url("file", 42)).to start_with("atom://") - end - end - end - - [:emacs, :emacsclient].each do |symbol| - context "when symbol is '#{symbol}'" do - let(:symbol) { symbol } - it "uses emacs:// scheme" do - expect(subject.url("file", 42)).to start_with("emacs://") - end - end - end - - [:macvim, :mvim].each do |symbol| - context "when symbol is '#{symbol}'" do - let(:symbol) { symbol } - - it "uses mvim:// scheme" do - expect(subject.url("file", 42)).to start_with("mvim://") - end - end - end - - [:sublime, :subl, :st].each do |symbol| - context "when symbol is '#{symbol}'" do - let(:symbol) { symbol } - - it "uses subl:// scheme" do - expect(subject.url("file", 42)).to start_with("subl://") - end - end - end - - [:textmate, :txmt, :tm].each do |symbol| - context "when symbol is '#{symbol}'" do - let(:symbol) { symbol } - - it "uses txmt:// scheme" do - expect(subject.url("file", 42)).to start_with("txmt://") - end - end - end - end - describe ".default_editor" do subject(:default_editor) { described_class.default_editor } before do @@ -230,4 +177,57 @@ end end end + + describe ".editor_from_symbol" do + subject { described_class.editor_from_symbol(symbol) } + + [:atom].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses atom:// scheme" do + expect(subject.url("file", 42)).to start_with("atom://") + end + end + end + + [:emacs, :emacsclient].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + it "uses emacs:// scheme" do + expect(subject.url("file", 42)).to start_with("emacs://") + end + end + end + + [:macvim, :mvim].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses mvim:// scheme" do + expect(subject.url("file", 42)).to start_with("mvim://") + end + end + end + + [:sublime, :subl, :st].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses subl:// scheme" do + expect(subject.url("file", 42)).to start_with("subl://") + end + end + end + + [:textmate, :txmt, :tm].each do |symbol| + context "when symbol is '#{symbol}'" do + let(:symbol) { symbol } + + it "uses txmt:// scheme" do + expect(subject.url("file", 42)).to start_with("txmt://") + end + end + end + end end From 45915e6a1c5e777f5fb975ef3094642a75fb6b66 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:31:28 -0500 Subject: [PATCH 40/73] Support for virtual and host paths --- lib/better_errors/editor.rb | 20 ++++++++++++++++- spec/better_errors/editor_spec.rb | 37 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/better_errors/editor.rb b/lib/better_errors/editor.rb index 06df7f4d..b8de8fb7 100644 --- a/lib/better_errors/editor.rb +++ b/lib/better_errors/editor.rb @@ -70,12 +70,30 @@ def initialize(url_proc) @url_proc = url_proc end - def url(file, line) + def url(raw_path, line) + if virtual_path && raw_path.start_with?(virtual_path) + if host_path + file = raw_path.sub(%r{\A#{virtual_path}}, host_path) + else + file = raw_path.sub(%r{\A#{virtual_path}/}, '') + end + else + file = raw_path + end + url_proc.call(file, line) end private attr_reader :url_proc + + def virtual_path + @virtual_path ||= ENV['BETTER_ERRORS_VIRTUAL_PATH'] + end + + def host_path + @host_path ||= ENV['BETTER_ERRORS_HOST_PATH'] + end end end diff --git a/spec/better_errors/editor_spec.rb b/spec/better_errors/editor_spec.rb index 033c05d5..ca0127a3 100644 --- a/spec/better_errors/editor_spec.rb +++ b/spec/better_errors/editor_spec.rb @@ -230,4 +230,41 @@ end end end + + describe "#url" do + subject(:url) { described_instance.url("/full/path/to/lib/file.rb", 42) } + let(:described_instance) { described_class.for_formatting_string("%{file_unencoded}")} + before do + ENV['BETTER_ERRORS_VIRTUAL_PATH'] = virtual_path + ENV['BETTER_ERRORS_HOST_PATH'] = host_path + end + let(:virtual_path) { nil } + let(:host_path) { nil } + + context "when $BETTER_ERRORS_VIRTUAL_PATH is set" do + let(:virtual_path) { "/full/path/to" } + + context "when $BETTER_ERRORS_HOST_PATH is not set" do + let(:host_path) { nil } + + it "removes the VIRTUAL_PATH prefix, making the path relative" do + expect(url).to eq("lib/file.rb") + end + end + + context "when $BETTER_ERRORS_HOST_PATH is set" do + let(:host_path) { '/Users/myname/Code' } + + it "replaces the VIRTUAL_PATH prefix with the HOST_PATH" do + expect(url).to eq("/Users/myname/Code/lib/file.rb") + end + end + end + + context "when $BETTER_ERRORS_VIRTUAL_PATH is not set" do + it "does not alter file paths" do + expect(url).to eq("/full/path/to/lib/file.rb") + end + end + end end From 123f9b327e8dc9c960c87dfaf876a8d519be57a4 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 15:33:22 -0500 Subject: [PATCH 41/73] Test invalid editor --- spec/better_errors_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/better_errors_spec.rb b/spec/better_errors_spec.rb index 0b5b6604..fbec6e7c 100644 --- a/spec/better_errors_spec.rb +++ b/spec/better_errors_spec.rb @@ -33,6 +33,12 @@ expect(subject.editor).to eq(:editor_from_symbol) end end + + context "when set to something else" do + it "raises an ArgumentError" do + expect { subject.editor = Class.new }.to raise_error(ArgumentError) + end + end end context "when no value has been set" do From 9d7256b441b4bc3becd90de663df887db7614186 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 4 Nov 2020 18:09:04 -0500 Subject: [PATCH 42/73] Fix "live shell" hint reappearing when frame changed --- lib/better_errors/templates/main.erb | 42 ++++++++++++------- lib/better_errors/templates/variable_info.erb | 2 +- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb index 5da0c530..c282c29f 100644 --- a/lib/better_errors/templates/main.erb +++ b/lib/better_errors/templates/main.erb @@ -595,6 +595,9 @@ color: #8080a0; padding-left: 20px; } + .console-has-been-used .live-console-hint { + display: none; + } .hint:before { content: '\25b2'; @@ -817,6 +820,28 @@ return html.replace(/&/, "&").replace(/ <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
+
This is a live shell. Type in here.
From 1f65a70f1dbba0f6e294ee820dfd1e957c46572d Mon Sep 17 00:00:00 2001 From: Sebastian Rachner Date: Thu, 5 Nov 2020 12:44:32 +0100 Subject: [PATCH 43/73] Fix setting editor with symbol --- lib/better_errors.rb | 2 +- spec/better_errors_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/better_errors.rb b/lib/better_errors.rb index af46bdd5..346a1b1d 100644 --- a/lib/better_errors.rb +++ b/lib/better_errors.rb @@ -106,7 +106,7 @@ def self.editor # def self.editor=(editor) if editor.is_a? Symbol - @editor = Editor.for_symbol(editor) + @editor = Editor.editor_from_symbol(editor) raise(ArgumentError, "Symbol #{editor} is not a symbol in the list of supported errors.") unless editor elsif editor.is_a? String @editor = Editor.for_formatting_string(editor) diff --git a/spec/better_errors_spec.rb b/spec/better_errors_spec.rb index fbec6e7c..10597158 100644 --- a/spec/better_errors_spec.rb +++ b/spec/better_errors_spec.rb @@ -4,7 +4,7 @@ describe ".editor" do context "when set to a specific value" do before do - allow(BetterErrors::Editor).to receive(:for_symbol).and_return(:editor_from_symbol) + allow(BetterErrors::Editor).to receive(:editor_from_symbol).and_return(:editor_from_symbol) allow(BetterErrors::Editor).to receive(:for_formatting_string).and_return(:editor_from_formatting_string) allow(BetterErrors::Editor).to receive(:for_proc).and_return(:editor_from_proc) end @@ -27,9 +27,9 @@ end context "when the value is a symbol" do - it "uses BetterErrors::Editor.for_symbol to set the value" do + it "uses BetterErrors::Editor.editor_from_symbol to set the value" do subject.editor = :subl - expect(BetterErrors::Editor).to have_received(:for_symbol).with(:subl) + expect(BetterErrors::Editor).to have_received(:editor_from_symbol).with(:subl) expect(subject.editor).to eq(:editor_from_symbol) end end From 6d555850780d13fc6864e7f8983d56ce4df8e7e2 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Wed, 2 Dec 2020 14:00:17 -0500 Subject: [PATCH 44/73] Tests for Rails 6.1 --- .github/workflows/ci.yml | 12 ++++++++++++ gemfiles/rails61.gemfile | 8 ++++++++ gemfiles/rails61_boc.gemfile | 9 +++++++++ gemfiles/rails61_haml.gemfile | 9 +++++++++ 4 files changed, 38 insertions(+) create mode 100644 gemfiles/rails61.gemfile create mode 100644 gemfiles/rails61_boc.gemfile create mode 100644 gemfiles/rails61_haml.gemfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 300ea272..598146b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,16 +31,19 @@ jobs: - rails51 - rails52 - rails60 + - rails61 - rails42_haml - rails50_haml - rails51_haml - rails52_haml - rails60_haml + - rails61_haml - rails42_boc - rails50_boc - rails51_boc - rails52_boc - rails60_boc + - rails61_boc - rack - rack_boc # - pry09 @@ -50,18 +53,27 @@ jobs: - { ruby: 2.2, gemfile: rails60 } - { ruby: 2.2, gemfile: rails60_boc } - { ruby: 2.2, gemfile: rails60_haml } + - { ruby: 2.2, gemfile: rails61 } + - { ruby: 2.2, gemfile: rails61_boc } + - { ruby: 2.2, gemfile: rails61_haml } - { ruby: 2.3, gemfile: rails42 } - { ruby: 2.3, gemfile: rails42_boc } - { ruby: 2.3, gemfile: rails42_haml } - { ruby: 2.3, gemfile: rails60 } - { ruby: 2.3, gemfile: rails60_boc } - { ruby: 2.3, gemfile: rails60_haml } + - { ruby: 2.3, gemfile: rails61 } + - { ruby: 2.3, gemfile: rails61_boc } + - { ruby: 2.3, gemfile: rails61_haml } - { ruby: 2.4, gemfile: rails42 } - { ruby: 2.4, gemfile: rails42_boc } - { ruby: 2.4, gemfile: rails42_haml } - { ruby: 2.4, gemfile: rails60 } - { ruby: 2.4, gemfile: rails60_boc } - { ruby: 2.4, gemfile: rails60_haml } + - { ruby: 2.4, gemfile: rails61 } + - { ruby: 2.4, gemfile: rails61_boc } + - { ruby: 2.4, gemfile: rails61_haml } - { ruby: 2.5, gemfile: rails42 } - { ruby: 2.5, gemfile: rails42_boc } - { ruby: 2.5, gemfile: rails42_haml } diff --git a/gemfiles/rails61.gemfile b/gemfiles/rails61.gemfile new file mode 100644 index 00000000..d185530c --- /dev/null +++ b/gemfiles/rails61.gemfile @@ -0,0 +1,8 @@ +source "https://rubygems.org" + +gem "rails", "~> 6.1.0rc" + +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false + +gemspec path: "../" diff --git a/gemfiles/rails61_boc.gemfile b/gemfiles/rails61_boc.gemfile new file mode 100644 index 00000000..50442047 --- /dev/null +++ b/gemfiles/rails61_boc.gemfile @@ -0,0 +1,9 @@ +source "https://rubygems.org" + +gem "rails", "~> 6.1.0rc" +gem "binding_of_caller" + +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false + +gemspec path: "../" diff --git a/gemfiles/rails61_haml.gemfile b/gemfiles/rails61_haml.gemfile new file mode 100644 index 00000000..6685996f --- /dev/null +++ b/gemfiles/rails61_haml.gemfile @@ -0,0 +1,9 @@ +source "https://rubygems.org" + +gem "rails", "~> 6.1.0rc" +gem "haml" + +gem 'simplecov', require: false +gem 'simplecov-lcov', require: false + +gemspec path: "../" From 66dee5e0f92bec8db907ef09156308168c711dab Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Fri, 11 Dec 2020 10:43:42 -0500 Subject: [PATCH 45/73] Content Security Policy for inline scripts --- lib/better_errors/error_page.rb | 2 +- lib/better_errors/middleware.rb | 21 +++++++++++++++++++-- lib/better_errors/templates/main.erb | 6 +++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/better_errors/error_page.rb b/lib/better_errors/error_page.rb index 1e44bd6e..2ff3cc15 100644 --- a/lib/better_errors/error_page.rb +++ b/lib/better_errors/error_page.rb @@ -26,7 +26,7 @@ def id @id ||= SecureRandom.hex(8) end - def render(template_name = "main", csrf_token = nil) + def render(template_name = "main", csrf_token = nil, csp_nonce = nil) binding.eval(self.class.template(template_name).src) rescue => e # Fix the backtrace, which doesn't identify the template that failed (within Better Errors). diff --git a/lib/better_errors/middleware.rb b/lib/better_errors/middleware.rb index 3a437819..a95d255b 100644 --- a/lib/better_errors/middleware.rb +++ b/lib/better_errors/middleware.rb @@ -94,12 +94,13 @@ def protected_app_call(env) def show_error_page(env, exception=nil) request = Rack::Request.new(env) csrf_token = request.cookies[CSRF_TOKEN_COOKIE_NAME] || SecureRandom.uuid + csp_nonce = SecureRandom.base64(12) type, content = if @error_page if text?(env) [ 'plain', @error_page.render('text') ] else - [ 'html', @error_page.render('main', csrf_token) ] + [ 'html', @error_page.render('main', csrf_token, csp_nonce) ] end else [ 'html', no_errors_page ] @@ -110,7 +111,23 @@ def show_error_page(env, exception=nil) status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code end - response = Rack::Response.new(content, status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }) + headers = { + "Content-Type" => "text/#{type}; charset=utf-8", + "Content-Security-Policy" => [ + "default-src 'self' https:", # TODO: remove https:? + "font-src 'self' https: data:", + "img-src 'self' https: data:", + "object-src 'none'", + # Specifying nonce makes a modern browser ignore 'unsafe-inline' which could still be set + # for older browsers without nonce support. + "script-src 'self' https: 'nonce-#{csp_nonce}' 'unsafe-inline'", + # Inline style is required by the syntax highlighter. + "style-src 'self' https: 'unsafe-inline'", + "connect-src 'self' https:", + ].join('; '), + } + + response = Rack::Response.new(content, status_code, headers) unless request.cookies[CSRF_TOKEN_COOKIE_NAME] response.set_cookie(CSRF_TOKEN_COOKIE_NAME, value: csrf_token, path: "/", httponly: true, same_site: :strict) diff --git a/lib/better_errors/templates/main.erb b/lib/better_errors/templates/main.erb index c282c29f..57bbdc1c 100644 --- a/lib/better_errors/templates/main.erb +++ b/lib/better_errors/templates/main.erb @@ -701,7 +701,7 @@ <%# IE8 compatibility crap %> - +

+ + Better Errors can't apply inline style, + possibly because you have a Content Security Policy along with Turbolinks. + But you can + open the interactive console in a new tab/window. + +

+

<%= exception_type %> at <%= request_path %>

@@ -791,9 +823,18 @@ - <% backtrace_frames.each_with_index do |frame, index| %> -
- <% end %> +
+
+

+ Better Errors can't run Javascript here (or apply inline style), + possibly because you have a Content Security Policy along with Turbolinks. + But you can + open the interactive console in a new tab/window. +

+ + <%== ErrorPage.render_template('variable_info', first_frame_variable_info) %> +
+