Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib/bootstrap.rb -> lib/boot/strap.rb #2676

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# New Relic Ruby Agent Release Notes

## dev

- **Bugfix: Incompatibility with Bootstrap**

Version <dev> fixes an incompatibility between the agent and the [Bootstrap](https://github.com/twbs/bootstrap-rubygem) gem caused by agent v9.10.0's introduction of a `lib/bootstrap.rb` file. Thank you to [@dorner](https://github.com/dorner) for reporting the bug and identifying the 'bootstrap' name collision as the root cause. [BUG#2675](https://github.com/newrelic/newrelic-ruby-agent/issues/2675) [PR#2676](https://github.com/newrelic/newrelic-ruby-agent/pull/2676)

## v9.10.0

Version 9.10.0 introduces instrumentation for DynamoDB, adds a new feature to automatically apply nonces from the Rails content security policy, fixes a bug that would cause an expected error to negatively impact a transaction's Apdex, and fixes the agent's autostart logic so that by default `rails runner` and `rails db` commands will not cause the agent to start.
Expand Down
22 changes: 9 additions & 13 deletions lib/bootstrap.rb → lib/boot/strap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
# - Next, use the "RUBYOPT" environment variable to require ("-r") this
# file (note that the ".rb" extension is dropped):
# ```
# export RUBYOPT="-r /newrelic/lib/bootstrap"
# export RUBYOPT="-r /newrelic/lib/boot/strap"
# ```
# - Add your New Relic license key as an environment variable.
# ```
Expand All @@ -50,7 +50,7 @@ def require(*_groups)
end

def require_newrelic
lib = File.dirname(__FILE__)
lib = File.expand_path('../..', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
Kernel.require NR_AGENT_GEM
end
Expand All @@ -65,40 +65,36 @@ def self.patch
check_for_rubyopt
check_for_bundler
Bundler::Runtime.prepend(NRBundlerPatch)
rescue StandardError => e
Kernel.warn "New Relic entrypoint at #{__FILE__} encountered an issue:\n #{e.message}"
end

private

def self.check_for_require
warn_and_exit "#{__FILE__} is meant to be required, not invoked directly" if $PROGRAM_NAME == __FILE__
raise "#{__FILE__} is meant to be required, not invoked directly" if $PROGRAM_NAME == __FILE__
end

def self.check_for_rubyopt
unless ENV[RUBYOPT].to_s.match?("-r #{__FILE__.rpartition('.').first}")
warn_and_exit "#{__FILE__} is meant to be required via the RUBYOPT env var"
raise "#{__FILE__} is meant to be required via the RUBYOPT env var"
end
end

def self.check_for_bundler
require_bundler

warn_and_exit 'Required Ruby Bundler class Bundler::Runtime not defined!' unless defined?(Bundler::Runtime)
raise 'Required Ruby Bundler class Bundler::Runtime not defined!' unless defined?(Bundler::Runtime)

unless Bundler::Runtime.method_defined?(:require)
warn_and_exit "The active Ruby Bundler instance doesn't offer Bundler::Runtime#require"
raise "The active Ruby Bundler instance doesn't offer Bundler::Runtime#require"
end
end

def self.require_bundler
require BUNDLER
rescue LoadError => e
warn_and_exit "Required Ruby library '#{BUNDLER}' could not be required - #{e}"
end

def self.warn_and_exit(msg)
warn "New Relic entrypoint at #{__FILE__} encountered an issue:\n\t#{msg}"

exit 1
raise "Required Ruby library '#{BUNDLER}' could not be required - #{e}"
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
# frozen_string_literal: true

require_relative '../test_helper'
require_relative '../../test_helper'

class NewRelicBootstrapTest < Minitest::Test
class PhonyBundler
Expand Down Expand Up @@ -34,13 +34,10 @@ def test_check_for_require
opn = $PROGRAM_NAME

$PROGRAM_NAME = bootstrap_file
msg = ''
NRBundlerPatcher.stub :warn_and_exit, proc { |m| msg = m } do

assert_raises(RuntimeError, 'meant to be required, not invoked') do
NRBundlerPatcher.check_for_require
end

assert_match(/meant to be required, not invoked/, msg,
'Expected check_for_require to complain when bootstrap is invoked directly')
ensure
$PROGRAM_NAME = opn
end
Expand All @@ -61,13 +58,9 @@ def test_check_for_bundler_class_not_defined
NRBundlerPatcher.stub :require_bundler, nil do
Bundler.send(:remove_const, :Runtime)

msg = ''
NRBundlerPatcher.stub :warn_and_exit, proc { |m| msg = m; Bundler.send(:const_set, :Runtime, oruntime) } do
assert_raises(RuntimeError, 'class Bundler::Runtime not defined!') do
NRBundlerPatcher.check_for_bundler
end

assert_match(/class Bundler::Runtime not defined!/, msg,
'Expected check_for_bundler to complain if Bundler::Runtime is not defined')
end
ensure
Bundler.send(:const_set, :Runtime, oruntime)
Expand All @@ -78,13 +71,9 @@ def test_check_for_bundler_method_not_defined

NRBundlerPatcher.stub :require_bundler, nil do
Bundler::Runtime.stub :method_defined?, false, [:require] do
msg = ''
NRBundlerPatcher.stub :warn_and_exit, proc { |m| msg = m } do
assert_raises(RuntimeError, "doesn't offer Bundler::Runtime#require") do
NRBundlerPatcher.check_for_bundler
end

assert_match(/doesn't offer Bundler::Runtime#require/, msg,
'Expected check_for_bundler to complain if Bundler::Runtime#require is not defined')
end
end
end
Expand All @@ -93,26 +82,26 @@ def test_require_bundler
skip_unless_minitest5_or_above

NRBundlerPatcher.stub :require, proc { |_gem| raise LoadError }, ['bundler'] do
msg = ''
NRBundlerPatcher.stub :warn_and_exit, proc { |m| msg = m } do
assert_raises(RuntimeError, 'could not be required') do
NRBundlerPatcher.check_for_bundler
end

assert_match(/could not be required/, msg,
'Expected require_bundler to complain if Bundler could not be required')
end
end

private

# Load the bootstrap file and anticipate the `warn` and `exit` calls
# with assertions
# Load the bootstrap file and anticipate the `warn` call
def require_bootstrap
assert_raises SystemExit do
assert_output(/New Relic entrypoint/) do
require_relative '../../lib/bootstrap'
end
msg = ''
loaded = nil
Kernel.stub :warn, proc { |m| msg = m } do
loaded = require_relative '../../../lib/boot/strap'
end

return unless loaded

assert_match(/New Relic entrypoint/, msg,
'Expected the initial requiring of boot/strap to generate a warning')
end

# Have the patcher patch our phony Bundler instead of the real one
Expand All @@ -129,6 +118,6 @@ def monkeypatch_phony_bundler
end

def bootstrap_file
@bootstrap_file ||= File.expand_path('../../../lib/bootstrap.rb', __FILE__)
@bootstrap_file ||= File.expand_path('../../../../lib/boot/strap.rb', __FILE__)
end
end
Loading