|
1 | 1 | require 'spec_helper' |
| 2 | +require 'timeout' |
2 | 3 |
|
3 | 4 | describe 'Configuration.logger' do |
4 | 5 |
|
|
19 | 20 | def run_app(name) |
20 | 21 | out_reader, out_writer = IO.pipe |
21 | 22 | Dir.chdir(File.join(File.dirname(__FILE__), "../fixtures/apps/#{name}")) do |
22 | | - Bundler.with_clean_env do |
23 | | - pid = Process.spawn('bundle install', |
24 | | - out: out_writer.fileno, |
25 | | - err: out_writer.fileno) |
26 | | - Process.waitpid(pid, 0) |
27 | | - pid = Process.spawn(@env, 'bundle exec rackup config.ru', |
28 | | - out: out_writer.fileno, |
29 | | - err: out_writer.fileno) |
30 | | - sleep(2) |
31 | | - Process.kill(1, pid) |
| 23 | + # Determine which Bundler env method to use based on availability |
| 24 | + # Ruby 4.0+ uses with_unbundled_env, Ruby 2-3.x uses with_clean_env, Ruby 1.9.2 has no env isolation |
| 25 | + if Bundler.respond_to?(:with_unbundled_env) |
| 26 | + Bundler.with_unbundled_env do |
| 27 | + execute_bundle_and_app(out_writer) |
| 28 | + end |
| 29 | + elsif Bundler.respond_to?(:with_clean_env) |
| 30 | + Bundler.with_clean_env do |
| 31 | + execute_bundle_and_app(out_writer) |
| 32 | + end |
| 33 | + else |
| 34 | + # Ruby 1.9.2: No env isolation available |
| 35 | + execute_bundle_and_app(out_writer) |
32 | 36 | end |
33 | 37 | end |
34 | 38 | out_writer.close |
35 | 39 | output = "" |
36 | 40 | output << out_reader.gets until out_reader.eof? |
37 | 41 | output |
38 | 42 | end |
| 43 | + |
| 44 | + private |
| 45 | + |
| 46 | + def execute_bundle_and_app(out_writer) |
| 47 | + # Handle Bundler install for different Ruby versions |
| 48 | + ruby_version = Gem::Version.new(RUBY_VERSION.dup) |
| 49 | + |
| 50 | + if ruby_version >= Gem::Version.new('3.4') |
| 51 | + # Ruby 3.4+: New Bundler syntax with separate steps |
| 52 | + pid = Process.spawn('bundle config set with "test"', |
| 53 | + out: out_writer.fileno, |
| 54 | + err: out_writer.fileno) |
| 55 | + Process.waitpid(pid, 0) |
| 56 | + pid = Process.spawn('bundle install', |
| 57 | + out: out_writer.fileno, |
| 58 | + err: out_writer.fileno) |
| 59 | + Process.waitpid(pid, 0) |
| 60 | + pid = Process.spawn('bundle binstubs --all', |
| 61 | + out: out_writer.fileno, |
| 62 | + err: out_writer.fileno) |
| 63 | + Process.waitpid(pid, 0) |
| 64 | + else |
| 65 | + # Ruby < 3.4: Legacy Bundler syntax (works for 1.9.2+) |
| 66 | + pid = Process.spawn('bundle install --with test --binstubs', |
| 67 | + out: out_writer.fileno, |
| 68 | + err: out_writer.fileno) |
| 69 | + Process.waitpid(pid, 0) |
| 70 | + end |
| 71 | + |
| 72 | + # Run the Rails app |
| 73 | + pid = Process.spawn(@env, 'bundle exec rackup config.ru', |
| 74 | + out: out_writer.fileno, |
| 75 | + err: out_writer.fileno) |
| 76 | + sleep(2) |
| 77 | + Process.kill('TERM', pid) |
| 78 | + begin |
| 79 | + # Wait up to 5 seconds for the process to exit |
| 80 | + Timeout.timeout(5) { Process.waitpid(pid) } |
| 81 | + rescue Timeout::Error |
| 82 | + # If still running, force kill |
| 83 | + Process.kill('KILL', pid) rescue nil |
| 84 | + Process.waitpid(pid) rescue nil |
| 85 | + rescue Errno::ECHILD |
| 86 | + # Already exited |
| 87 | + end |
| 88 | + end |
39 | 89 | context 'sets an API key using the BUGSNAG_API_KEY env var' do |
40 | 90 | it 'does not log a warning' do |
41 | 91 | skip "Incompatible with Ruby <2.0 and JRuby" if incompatible |
@@ -81,19 +131,45 @@ def run_app(name) |
81 | 131 |
|
82 | 132 | context 'in a script' do |
83 | 133 | key_warning = /\[Bugsnag\] .* No valid API key has been set, notifications will not be sent/ |
84 | | - |
| 134 | + |
85 | 135 | def run_app(name) |
86 | 136 | output = '' |
87 | 137 | Dir.chdir(File.join(File.dirname(__FILE__), "../fixtures/apps/scripts")) do |
88 | | - Bundler.with_clean_env do |
89 | | - IO.popen([@env, 'bundle', 'exec', 'ruby', "#{name}.rb", err: [:child, :out]]) do |io| |
90 | | - output << io.read |
| 138 | + # Determine which Bundler env method to use based on availability |
| 139 | + # Ruby 4.0+ uses with_unbundled_env, Ruby 2-3.x uses with_clean_env, Ruby 1.9.2 has no env isolation |
| 140 | + if Bundler.respond_to?(:with_unbundled_env) |
| 141 | + Bundler.with_unbundled_env do |
| 142 | + execute_script(name, output) |
91 | 143 | end |
| 144 | + elsif Bundler.respond_to?(:with_clean_env) |
| 145 | + Bundler.with_clean_env do |
| 146 | + execute_script(name, output) |
| 147 | + end |
| 148 | + else |
| 149 | + # Ruby 1.9.2: No env isolation available |
| 150 | + execute_script(name, output) |
92 | 151 | end |
93 | 152 | end |
94 | 153 | output |
95 | 154 | end |
96 | 155 |
|
| 156 | + private |
| 157 | + |
| 158 | + def execute_script(name, output) |
| 159 | + if RUBY_VERSION < '2.0.0' |
| 160 | + # Ruby 1.9.x: Use shell string with environment variables |
| 161 | + env_str = @env.map { |k, v| "#{k}='#{v}'" }.join(' ') |
| 162 | + IO.popen("#{env_str} bundle exec ruby #{name}.rb 2>&1") do |io| |
| 163 | + output << io.read |
| 164 | + end |
| 165 | + else |
| 166 | + # Ruby 2.0+: Use array form with env hash and stderr redirection |
| 167 | + IO.popen([@env, 'bundle', 'exec', 'ruby', "#{name}.rb", err: [:child, :out]]) do |io| |
| 168 | + output << io.read |
| 169 | + end |
| 170 | + end |
| 171 | + end |
| 172 | + |
97 | 173 | context 'sets an API key using the BUGSNAG_API_KEY env var' do |
98 | 174 | it 'does not log a warning' do |
99 | 175 | @env['BUGSNAG_API_KEY'] = 'c34a2472bd240ac0ab0f52715bbdc05d' |
|
0 commit comments