diff --git a/build_tools/services.rb b/build_tools/services.rb index 8bf91b2eb42..a78ed7ce825 100644 --- a/build_tools/services.rb +++ b/build_tools/services.rb @@ -9,10 +9,10 @@ class ServiceEnumerator MANIFEST_PATH = File.expand_path('../../services.json', __FILE__) # Minimum `aws-sdk-core` version for new gem builds - MINIMUM_CORE_VERSION = "3.244.0" + MINIMUM_CORE_VERSION = "3.247.0" # Minimum `aws-sdk-core` version for new S3 gem builds - MINIMUM_CORE_VERSION_S3 = "3.244.0" + MINIMUM_CORE_VERSION_S3 = "3.247.0" EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration" diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index 161ec602f37..a1259ea6a31 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,5 +1,6 @@ Unreleased Changes ------------------ +* Feature - Add YJIT & ZJIT tracking to user agent. 3.246.0 (2026-04-23) ------------------ diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index c5792f666ce..7bd7546338f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -171,7 +171,16 @@ def os_metadata # Used to be RUBY_ENGINE/RUBY_VERSION def language_metadata - "lang/#{RUBY_ENGINE}##{RUBY_ENGINE_VERSION} md/#{RUBY_VERSION}" + metadata = "lang/#{RUBY_ENGINE}##{RUBY_ENGINE_VERSION} md/#{RUBY_VERSION}" + return metadata unless RUBY_ENGINE == 'ruby' + + %i[YJIT ZJIT].each do |jit| + next unless RubyVM.const_defined?(jit) + + mode = RubyVM.const_get(jit) + metadata += " md/#{jit.to_s.downcase}" if mode.respond_to?(:enabled?) && mode.enabled? + end + metadata end def env_metadata diff --git a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb index 18063f600fb..ab7fc1fc6ec 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb @@ -89,6 +89,66 @@ def assert_header(expected, actual) end end + def stub_jit(name, enabled:) + if enabled + jit_module = double(enabled?: true) + stub_const("RubyVM::#{name}", jit_module) + else + hide_const("RubyVM::#{name}") + end + end + + # Added tests manually instead of modifying cross-SDK test JSON since JIT info is specific to Ruby. + context 'JIT metadata' do + before do + allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('linux') + allow(RbConfig::CONFIG).to receive(:[]).with('host_cpu').and_return('x86_64') + allow(Gem::Platform).to receive(:local).and_return(double(version: '1.0')) + end + + def user_agent_for(client) + resp = client.example_operation + resp.context.http_request.headers['User-Agent'] + end + + it 'includes md/yjit when YJIT is enabled', skip: (RUBY_ENGINE != 'ruby') do + stub_jit(:YJIT, enabled: true) + stub_jit(:ZJIT, enabled: false) + + expect(user_agent_for(client)).to include('md/yjit') + expect(user_agent_for(client)).not_to include('md/zjit') + end + + it 'includes md/zjit when ZJIT is enabled', skip: (RUBY_ENGINE != 'ruby') do + stub_jit(:YJIT, enabled: false) + stub_jit(:ZJIT, enabled: true) + + expect(user_agent_for(client)).to include('md/zjit') + expect(user_agent_for(client)).not_to include('md/yjit') + end + + it 'includes neither when both are disabled' do + stub_jit(:YJIT, enabled: false) + stub_jit(:ZJIT, enabled: false) + + ua = user_agent_for(client) + expect(ua).not_to include('md/yjit') + expect(ua).not_to include('md/zjit') + end + + it 'includes neither on non-CRuby engines' do + stub_const('RUBY_ENGINE', 'jruby') + stub_const('RUBY_ENGINE_VERSION', '9.4.0.0') + stub_jit(:YJIT, enabled: false) + stub_jit(:ZJIT, enabled: false) + + ua = user_agent_for(client) + expect(ua).to include('lang/jruby#9.4.0.0') + expect(ua).not_to include('md/yjit') + expect(ua).not_to include('md/zjit') + end + end + context 'test runner' do tests = JSON.load_file( File.join(File.dirname(__FILE__), 'user_agent_tests.json')