Skip to content
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
23 changes: 20 additions & 3 deletions .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4']
ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4', '4.0']
optional-groups: ['test sidekiq']
include:
- ruby-version: '1.9'
Expand All @@ -21,7 +21,12 @@ jobs:
optional-groups: 'test'
- ruby-version: 'jruby'
optional-groups: 'test'

# Mark Ruby versions >= 3.4 as using modern bundler
- ruby-version: '3.4'
modern-bundler: true
- ruby-version: '4.0'
modern-bundler: true

steps:
- uses: actions/checkout@v3

Expand All @@ -30,8 +35,20 @@ jobs:
with:
ruby-version: ${{ matrix.ruby-version }}

- run: bundle install --with "${{ matrix.optional-groups }}" --binstubs
# For Ruby 3.4+ (Bundler ≥ 2.4.0), use bundle config set with and bundle binstubs --all,
# since the --with and --binstubs flags have been removed from modern Bundler versions
- name: Install dependencies (Ruby >= 3.4)
if: ${{ matrix.modern-bundler == true }}
run: |
bundle config set with "${{ matrix.optional-groups }}"
bundle install
bundle binstubs --all

# For Ruby < 3.4, use the legacy flags which are still supported
- name: Install dependencies (Ruby < 3.4)
if: ${{ matrix.modern-bundler != true }}
run: bundle install --with "${{ matrix.optional-groups }}" --binstubs

- run: ./bin/rake spec

linting:
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ group :test, optional: true do
# WEBrick is no longer in the stdlib in Ruby 3.0
gem 'webrick' if ruby_version >= Gem::Version.new('3.0.0')

# OpenStruct removed from default gems in Ruby 4.0+
gem 'ostruct' if ruby_version >= Gem::Version.new('4.0')

gem 'rexml', '< 3.2.5' if ruby_version == Gem::Version.new('2.0.0')

if ruby_version >= Gem::Version.new('2.2.0') && ruby_version < Gem::Version.new('2.4.0')
Expand Down
17 changes: 14 additions & 3 deletions spec/fixtures/apps/rails-initializer-config/Gemfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
source 'https://rubygems.org'

ruby_version = Gem::Version.new(RUBY_VERSION.dup)

if ruby_version >= Gem::Version.new('3.4')
gem 'mutex_m', '0.3.0'
gem 'base64', '0.2.0'
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
# Only use logger 1.6.5 for Ruby < 4.0, otherwise use >= 1.7 for compatibility with bugsnag
if ruby_version < Gem::Version.new('4.0')
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
else
gem 'logger', '>= 1.7', '< 2.0'
gem 'bigdecimal', '>= 4.0.0', '< 5.0.0'
gem 'ostruct'
gem 'benchmark'
end
end

gem 'railties', ruby_version <= Gem::Version.new('2.6') ? '4.2.10' : '~> 6.0.2', require: %w(action_controller rails)
gem 'rake', ruby_version <= Gem::Version.new('1.9.3') ? '~> 11.3.0' : '~> 12.3.0'
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
if ruby_version < Gem::Version.new('4.0')
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
end
gem 'nokogiri', ruby_version < Gem::Version.new('2.6') ? '1.6.8' : '~> 1.13.9'
gem 'bugsnag', path: '../../../..'
16 changes: 13 additions & 3 deletions spec/fixtures/apps/rails-invalid-initializer-config/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ ruby_version = Gem::Version.new(RUBY_VERSION.dup)
if ruby_version >= Gem::Version.new('3.4')
gem 'mutex_m', '0.3.0'
gem 'base64', '0.2.0'
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
# Only use logger 1.6.5 for Ruby < 4.0, otherwise use >= 1.7 for compatibility with bugsnag
if ruby_version < Gem::Version.new('4.0')
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
else
gem 'logger', '>= 1.7', '< 2.0'
gem 'bigdecimal', '>= 4.0.0', '< 5.0.0'
gem 'ostruct'
gem 'benchmark'
end
end

gem 'railties', ruby_version <= Gem::Version.new('2.6') ? '4.2.10' : '~> 6.0.2', require: %w(action_controller rails)
gem 'rake', ruby_version <= Gem::Version.new('1.9.3') ? '~> 11.3.0' : '~> 12.3.0'
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
if ruby_version < Gem::Version.new('4.0')
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
end
gem 'nokogiri', ruby_version < Gem::Version.new('2.6') ? '1.6.8' : '~> 1.13.9'
gem 'bugsnag', path: '../../../..'
16 changes: 13 additions & 3 deletions spec/fixtures/apps/rails-no-config/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,22 @@ ruby_version = Gem::Version.new(RUBY_VERSION.dup)
if ruby_version >= Gem::Version.new('3.4')
gem 'mutex_m', '0.3.0'
gem 'base64', '0.2.0'
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
# Only use logger 1.6.5 for Ruby < 4.0, otherwise use >= 1.7 for compatibility with bugsnag
if ruby_version < Gem::Version.new('4.0')
gem 'logger', '1.6.5'
gem 'bigdecimal', '3.1.9'
else
gem 'logger', '>= 1.7', '< 2.0'
gem 'bigdecimal', '>= 4.0.0', '< 5.0.0'
gem 'ostruct'
gem 'benchmark'
end
end

gem 'railties', ruby_version <= Gem::Version.new('2.6') ? '4.2.10' : '~> 6.0.2', require: %w(action_controller rails)
gem 'rake', ruby_version <= Gem::Version.new('1.9.3') ? '~> 11.3.0' : '~> 12.3.0'
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
if ruby_version < Gem::Version.new('4.0')
gem 'minitest', ruby_version <= Gem::Version.new('2.2') ? '5.11.3' : '~> 5.14.0'
end
gem 'nokogiri', ruby_version < Gem::Version.new('2.6') ? '1.6.8' : '~> 1.13.9'
gem 'bugsnag', path: '../../../..'
104 changes: 90 additions & 14 deletions spec/integrations/logger_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'spec_helper'
require 'timeout'

describe 'Configuration.logger' do

Expand All @@ -19,23 +20,72 @@
def run_app(name)
out_reader, out_writer = IO.pipe
Dir.chdir(File.join(File.dirname(__FILE__), "../fixtures/apps/#{name}")) do
Bundler.with_clean_env do
pid = Process.spawn('bundle install',
out: out_writer.fileno,
err: out_writer.fileno)
Process.waitpid(pid, 0)
pid = Process.spawn(@env, 'bundle exec rackup config.ru',
out: out_writer.fileno,
err: out_writer.fileno)
sleep(2)
Process.kill(1, pid)
# Determine which Bundler env method to use based on availability
# Ruby 4.0+ uses with_unbundled_env, Ruby 2-3.x uses with_clean_env, Ruby 1.9.2 has no env isolation
if Bundler.respond_to?(:with_unbundled_env)
Bundler.with_unbundled_env do
execute_bundle_and_app(out_writer)
end
Comment thread
SB-khushbum marked this conversation as resolved.
elsif Bundler.respond_to?(:with_clean_env)
Bundler.with_clean_env do
execute_bundle_and_app(out_writer)
end
else
# Ruby 1.9.2: No env isolation available
execute_bundle_and_app(out_writer)
end
end
out_writer.close
output = ""
output << out_reader.gets until out_reader.eof?
output
end

private

def execute_bundle_and_app(out_writer)
# Handle Bundler install for different Ruby versions
ruby_version = Gem::Version.new(RUBY_VERSION.dup)

if ruby_version >= Gem::Version.new('3.4')
# Ruby 3.4+: New Bundler syntax with separate steps
pid = Process.spawn('bundle config set with "test"',
out: out_writer.fileno,
err: out_writer.fileno)
Process.waitpid(pid, 0)
pid = Process.spawn('bundle install',
out: out_writer.fileno,
err: out_writer.fileno)
Process.waitpid(pid, 0)
pid = Process.spawn('bundle binstubs --all',
out: out_writer.fileno,
err: out_writer.fileno)
Process.waitpid(pid, 0)
else
# Ruby < 3.4: Legacy Bundler syntax (works for 1.9.2+)
pid = Process.spawn('bundle install --with test --binstubs',
out: out_writer.fileno,
err: out_writer.fileno)
Process.waitpid(pid, 0)
end

# Run the Rails app
pid = Process.spawn(@env, 'bundle exec rackup config.ru',
out: out_writer.fileno,
err: out_writer.fileno)
sleep(2)
Process.kill('TERM', pid)
begin
# Wait up to 5 seconds for the process to exit
Timeout.timeout(5) { Process.waitpid(pid) }
rescue Timeout::Error
Comment thread
SB-khushbum marked this conversation as resolved.
# If still running, force kill
Process.kill('KILL', pid) rescue nil
Process.waitpid(pid) rescue nil
Comment thread
SB-khushbum marked this conversation as resolved.
rescue Errno::ECHILD
# Already exited
end
end
Comment thread
SB-khushbum marked this conversation as resolved.
context 'sets an API key using the BUGSNAG_API_KEY env var' do
it 'does not log a warning' do
skip "Incompatible with Ruby <2.0 and JRuby" if incompatible
Expand Down Expand Up @@ -81,19 +131,45 @@ def run_app(name)

context 'in a script' do
key_warning = /\[Bugsnag\] .* No valid API key has been set, notifications will not be sent/

def run_app(name)
output = ''
Dir.chdir(File.join(File.dirname(__FILE__), "../fixtures/apps/scripts")) do
Bundler.with_clean_env do
IO.popen([@env, 'bundle', 'exec', 'ruby', "#{name}.rb", err: [:child, :out]]) do |io|
output << io.read
# Determine which Bundler env method to use based on availability
# Ruby 4.0+ uses with_unbundled_env, Ruby 2-3.x uses with_clean_env, Ruby 1.9.2 has no env isolation
if Bundler.respond_to?(:with_unbundled_env)
Bundler.with_unbundled_env do
execute_script(name, output)
end
elsif Bundler.respond_to?(:with_clean_env)
Bundler.with_clean_env do
execute_script(name, output)
end
else
# Ruby 1.9.2: No env isolation available
execute_script(name, output)
end
end
output
end

private

def execute_script(name, output)
if RUBY_VERSION < '2.0.0'
# Ruby 1.9.x: Use shell string with environment variables
env_str = @env.map { |k, v| "#{k}='#{v}'" }.join(' ')
IO.popen("#{env_str} bundle exec ruby #{name}.rb 2>&1") do |io|
output << io.read
end
else
# Ruby 2.0+: Use array form with env hash and stderr redirection
IO.popen([@env, 'bundle', 'exec', 'ruby', "#{name}.rb", err: [:child, :out]]) do |io|
output << io.read
end
end
end

context 'sets an API key using the BUGSNAG_API_KEY env var' do
it 'does not log a warning' do
@env['BUGSNAG_API_KEY'] = 'c34a2472bd240ac0ab0f52715bbdc05d'
Expand Down
3 changes: 2 additions & 1 deletion spec/report_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1993,7 +1993,8 @@ def to_s
# - Report.generate_exceptions_list
# - Report.generate_exceptions_list | raw_exceptions.map
# - Report.generate_exceptions_list | raw_exceptions.map | block
expect(bugsnag_count).to eq(6)
expect(bugsnag_count).to be_between(5, 6).inclusive
# Updated for Ruby 4.0 compatibility: frame count may vary due to changes in exception handling or stack trace generation
}
end

Expand Down
Loading