From 68283321429393ec1d0bed149dadd5ded69a97a9 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 23 Jul 2026 08:23:59 +0100 Subject: [PATCH 1/5] Update gems and rubocop config; --- ruby/.rubocop.yml | 4 ++-- ruby/cucumber-ci-environment.gemspec | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ruby/.rubocop.yml b/ruby/.rubocop.yml index 92fa0e44..d9e6d3b6 100644 --- a/ruby/.rubocop.yml +++ b/ruby/.rubocop.yml @@ -1,12 +1,12 @@ inherit_from: .rubocop_todo.yml -require: +plugins: - rubocop-performance - rubocop-rake - rubocop-rspec AllCops: - TargetRubyVersion: 3.2 + TargetRubyVersion: 3.3 NewCops: enable # Keep dev dependencies in gemspec diff --git a/ruby/cucumber-ci-environment.gemspec b/ruby/cucumber-ci-environment.gemspec index 333aa3cb..b2573beb 100644 --- a/ruby/cucumber-ci-environment.gemspec +++ b/ruby/cucumber-ci-environment.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/cucumber/ci-environment' s.platform = Gem::Platform::RUBY s.license = 'MIT' - s.required_ruby_version = '>= 3.2' + s.required_ruby_version = '>= 3.3' s.required_rubygems_version = '>= 3.2.8' s.metadata = { @@ -23,10 +23,10 @@ Gem::Specification.new do |s| s.add_development_dependency 'rake', '~> 13.3' s.add_development_dependency 'rspec', '~> 3.13' - s.add_development_dependency 'rubocop', '~> 1.81.0' - s.add_development_dependency 'rubocop-performance', '~> 1.23.0' - s.add_development_dependency 'rubocop-rake', '~> 0.6.0' - s.add_development_dependency 'rubocop-rspec', '~> 3.7.0' + s.add_development_dependency 'rubocop', '~> 1.88.2' + s.add_development_dependency 'rubocop-performance', '~> 1.26.1' + s.add_development_dependency 'rubocop-rake', '~> 0.7.1' + s.add_development_dependency 'rubocop-rspec', '~> 3.10.2' s.files = Dir['README.md', 'LICENSE', 'lib/**/*'] s.rdoc_options = ['--charset=UTF-8'] From b6e4494854a9246a46a572d9a731843ecec3f31e Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 23 Jul 2026 08:39:07 +0100 Subject: [PATCH 2/5] Improve speed of load in specs --- ruby/lib/cucumber/ci_environment.rb | 3 ++- ruby/spec/cucumber/ci_environment_spec.rb | 1 - ruby/spec/cucumber/variable_expression_spec.rb | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ruby/lib/cucumber/ci_environment.rb b/ruby/lib/cucumber/ci_environment.rb index f713bb59..063d4510 100644 --- a/ruby/lib/cucumber/ci_environment.rb +++ b/ruby/lib/cucumber/ci_environment.rb @@ -2,7 +2,8 @@ require 'uri' require 'json' -require 'cucumber/variable_expression' + +require_relative 'variable_expression' module Cucumber class CiEnvironment diff --git a/ruby/spec/cucumber/ci_environment_spec.rb b/ruby/spec/cucumber/ci_environment_spec.rb index 18924783..4746692b 100644 --- a/ruby/spec/cucumber/ci_environment_spec.rb +++ b/ruby/spec/cucumber/ci_environment_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'cucumber/ci_environment' -require 'json' describe Cucumber::CiEnvironment do describe '.detect_ci_environment' do diff --git a/ruby/spec/cucumber/variable_expression_spec.rb b/ruby/spec/cucumber/variable_expression_spec.rb index 06faefc5..8f7f9d5d 100644 --- a/ruby/spec/cucumber/variable_expression_spec.rb +++ b/ruby/spec/cucumber/variable_expression_spec.rb @@ -4,39 +4,43 @@ describe Cucumber::VariableExpression do describe '.evaluate' do - subject(:ci_environment) { Cucumber::CiEnvironment } + subject(:variable_klazz) do + Class.new do + extend Cucumber::VariableExpression + end + end it 'returns nil when a variable is undefined' do expression = 'hello-${SOME_VAR}' - result = ci_environment.evaluate(expression, {}) + result = variable_klazz.evaluate(expression, {}) expect(result).to be_nil end it 'gets a value without replacement' do expression = '${SOME_VAR}' - result = ci_environment.evaluate(expression, { 'SOME_VAR' => 'some_value' }) + result = variable_klazz.evaluate(expression, { 'SOME_VAR' => 'some_value' }) expect(result).to eq('some_value') end it 'captures a group' do expression = '${SOME_REF/refs/heads/(.*)/\\1}' - result = ci_environment.evaluate(expression, { 'SOME_REF' => 'refs/heads/main' }) + result = variable_klazz.evaluate(expression, { 'SOME_REF' => 'refs/heads/main' }) expect(result).to eq('main') end it 'works with star wildcard in var' do expression = '${GO_SCM_*_PR_BRANCH/.*:(.*)/\\1}' - result = ci_environment.evaluate(expression, { 'GO_SCM_MY_MATERIAL_PR_BRANCH' => 'ashwankthkumar:feature-1' }) + result = variable_klazz.evaluate(expression, { 'GO_SCM_MY_MATERIAL_PR_BRANCH' => 'ashwankthkumar:feature-1' }) expect(result).to eq('feature-1') end - it 'ci_environment.evaluates a complex expression' do + it 'variable_klazz.evaluates a complex expression' do expression = 'hello-${VAR1}-${VAR2/(.*) (.*)/\\2-\\1}-world' - result = ci_environment.evaluate(expression, { 'VAR1' => 'amazing', 'VAR2' => 'gorgeous beautiful' }) + result = variable_klazz.evaluate(expression, { 'VAR1' => 'amazing', 'VAR2' => 'gorgeous beautiful' }) expect(result).to eq('hello-amazing-beautiful-gorgeous-world') end From fae3f83179ce74d5f935757a5119529a43d92876 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 23 Jul 2026 08:46:43 +0100 Subject: [PATCH 3/5] Add regex handling to ensure no DDoS potential during regex calculation --- CHANGELOG.md | 2 ++ ruby/lib/cucumber/variable_expression.rb | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 103c2741..3f893fe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Ruby] Ensure `CiEnvironments.json` is published (in new dir), in gem package - BREAKING CHANGE: [Ruby] change `VariableExpression` module namespace to be top level alongside `CiEnvironment` module +- [Ruby] Add a regex timeout wrapper when calling `VariableExpression.evaluate` ensuring each calculation takes at max 5 seconds +- [Ruby] Minimum ruby version is now 3.3 ## [14.0.0] - 2026-06-11 ### Changed diff --git a/ruby/lib/cucumber/variable_expression.rb b/ruby/lib/cucumber/variable_expression.rb index 2d334adb..8e59b142 100644 --- a/ruby/lib/cucumber/variable_expression.rb +++ b/ruby/lib/cucumber/variable_expression.rb @@ -3,6 +3,9 @@ module Cucumber module VariableExpression def evaluate(expression, env) + previous_timeout = Regexp.timeout + + Regexp.timeout = 5 return nil if expression.nil? expression.gsub(/\${(.*?)(?:(? Date: Thu, 23 Jul 2026 08:50:25 +0100 Subject: [PATCH 4/5] Remove non-permissible ci flow --- .github/workflows/test-ruby.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-ruby.yaml b/.github/workflows/test-ruby.yaml index bee8bb88..374e9ab8 100644 --- a/.github/workflows/test-ruby.yaml +++ b/.github/workflows/test-ruby.yaml @@ -28,7 +28,7 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest] - ruby: ['3.2', '3.3', '3.4', '4.0'] + ruby: ['3.3', '3.4', '4.0'] include: - os: windows-latest ruby: '4.0' From fb6fe9ed3e7127d56b83eb59bedd8d2309a1cab8 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 23 Jul 2026 09:46:28 +0100 Subject: [PATCH 5/5] Remove regex timeout functionality --- CHANGELOG.md | 1 - ruby/lib/cucumber/variable_expression.rb | 5 ----- 2 files changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f893fe1..51b1ecef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - [Ruby] Ensure `CiEnvironments.json` is published (in new dir), in gem package - BREAKING CHANGE: [Ruby] change `VariableExpression` module namespace to be top level alongside `CiEnvironment` module -- [Ruby] Add a regex timeout wrapper when calling `VariableExpression.evaluate` ensuring each calculation takes at max 5 seconds - [Ruby] Minimum ruby version is now 3.3 ## [14.0.0] - 2026-06-11 diff --git a/ruby/lib/cucumber/variable_expression.rb b/ruby/lib/cucumber/variable_expression.rb index 8e59b142..2d334adb 100644 --- a/ruby/lib/cucumber/variable_expression.rb +++ b/ruby/lib/cucumber/variable_expression.rb @@ -3,9 +3,6 @@ module Cucumber module VariableExpression def evaluate(expression, env) - previous_timeout = Regexp.timeout - - Regexp.timeout = 5 return nil if expression.nil? expression.gsub(/\${(.*?)(?:(?