Skip to content

Commit 4a50656

Browse files
authored
feat: Require Ruby 2.7 or later
fix: Improved hashing algorithm for opaque event objects Signed-off-by: Daniel Azuma <[email protected]>
1 parent 4998597 commit 4a50656

File tree

12 files changed

+81
-72
lines changed

12 files changed

+81
-72
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,39 @@ jobs:
1515
strategy:
1616
matrix:
1717
include:
18-
- os: ubuntu-latest
19-
ruby: "2.5"
20-
- os: ubuntu-latest
21-
ruby: "2.6"
2218
- os: ubuntu-latest
2319
ruby: "2.7"
20+
flags: "--test --cucumber"
2421
- os: ubuntu-latest
2522
ruby: "3.0"
23+
flags: "--test --cucumber"
2624
- os: ubuntu-latest
2725
ruby: "3.1"
26+
flags: "--test --cucumber"
2827
- os: ubuntu-latest
2928
ruby: "3.2"
30-
tool: ci
29+
flags: "--test --cucumber"
30+
- os: ubuntu-latest
31+
ruby: "3.3"
32+
flags: "--test --cucumber"
33+
- os: ubuntu-latest
34+
ruby: "3.4"
35+
flags: "--test --cucumber"
36+
- os: ubuntu-latest
37+
ruby: "3.4"
38+
flags: "--rubocop --yard --build"
3139
- os: ubuntu-latest
3240
ruby: jruby
41+
flags: "--test --cucumber"
3342
- os: ubuntu-latest
3443
ruby: truffleruby
44+
flags: "--test --cucumber"
3545
- os: macos-latest
36-
ruby: "3.2"
46+
ruby: "3.4"
47+
flags: "--test --cucumber"
3748
- os: windows-latest
38-
ruby: "3.2"
49+
ruby: "3.4"
50+
flags: "--test --cucumber"
3951
fail-fast: false
4052
runs-on: ${{ matrix.os }}
4153
steps:
@@ -44,13 +56,11 @@ jobs:
4456
with:
4557
ruby-version: ${{ matrix.ruby }}
4658
- name: Checkout repo
47-
uses: actions/checkout@v2
59+
uses: actions/checkout@v5
4860
- name: Install dependencies
4961
shell: bash
5062
run: "bundle install && gem install --no-document toys"
51-
- name: Run ${{ matrix.tool || 'test' }}
63+
- name: Run ${{ matrix.flags }}
5264
shell: bash
53-
env:
54-
MT_COMPAT: "true"
5565
run: |
56-
toys "${{ matrix.tool || 'test' }}" < /dev/null
66+
toys ci --only ${{ matrix.flags }} < /dev/null

.toys/ci.rb

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
# frozen_string_literal: true
22

3-
desc "Run all CI checks"
4-
5-
include :exec, result_callback: :handle_result
6-
include :terminal
3+
load_git remote: "https://github.com/dazuma/toys.git",
4+
path: "common-tools/ci",
5+
update: 3600
76

8-
def handle_result result
9-
if result.success?
10-
puts "** #{result.name} passed\n\n", :green, :bold
11-
else
12-
puts "** CI terminated: #{result.name} failed!", :red, :bold
13-
exit 1
14-
end
15-
end
7+
desc "Run all CI checks"
168

17-
def run
18-
::Dir.chdir context_directory
19-
exec_tool ["test"], name: "Tests"
20-
exec_tool ["cucumber"], name: "Behaviors"
21-
exec_tool ["rubocop"], name: "Style checker"
22-
exec_tool ["yardoc"], name: "Docs generation"
23-
exec_tool ["build"], name: "Gem build"
9+
expand("toys-ci") do |toys_ci|
10+
toys_ci.only_flag = true
11+
toys_ci.fail_fast_flag = true
12+
toys_ci.job("Bundle update", flag: :bundle, exec: ["bundle", "update"])
13+
toys_ci.job("Rubocop", flag: :rubocop, tool: ["rubocop"])
14+
toys_ci.job("Tests", flag: :test, tool: ["test"])
15+
toys_ci.job("Cucumber", flag: :cucumber, tool: ["cucumber"])
16+
toys_ci.job("Yardoc", flag: :yard, tool: ["yardoc"])
17+
toys_ci.job("Gem build", flag: :build, tool: ["build"])
2418
end

.toys/cucumber.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
toys_version! ">= 0.12"
3+
toys_version! ">= 0.15"
44

55
desc "Run cucumber tests"
66

Gemfile

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
source "https://rubygems.org"
22
gemspec
33

4-
gem "cucumber", "7.0"
5-
gem "google-style", "~> 1.25.1"
6-
gem "minitest", "~> 5.14"
7-
gem "minitest-focus", "~> 1.1"
8-
gem "minitest-rg", "~> 5.2"
9-
gem "rack", "~> 2.2"
10-
gem "redcarpet", "~> 3.5" unless ::RUBY_PLATFORM == "java"
11-
gem "webrick", "~> 1.7"
12-
gem "yard", "~> 0.9.25"
4+
gem "base64", "~> 0.3"
5+
gem "cucumber", "~> 9.2"
6+
gem "google-style", "~> 1.27.1"
7+
gem "logger", "~> 1.7"
8+
gem "minitest", "~> 5.25"
9+
gem "minitest-focus", "~> 1.4"
10+
gem "minitest-rg", "~> 5.3"
11+
gem "ostruct", "~> 0.6"
12+
gem "rack", "~> 3.2"
13+
gem "redcarpet", "~> 3.6" unless ::RUBY_PLATFORM == "java"
14+
gem "webrick", "~> 1.9"
15+
gem "yard", "~> 0.9.37"

cloud_events.gemspec

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# frozen_string_literal: true
22

3-
lib = ::File.expand_path "lib", __dir__
4-
$LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
5-
require "cloud_events/version"
3+
require_relative "lib/cloud_events/version"
64
version = ::CloudEvents::VERSION
75

86
::Gem::Specification.new do |spec|
@@ -13,15 +11,15 @@ version = ::CloudEvents::VERSION
1311
spec.email = ["[email protected]"]
1412

1513
spec.summary = "Ruby SDK for CloudEvents"
16-
spec.description = \
17-
"The official Ruby implementation of the CloudEvents Specification." \
18-
" Provides data types for events, and HTTP/JSON bindings for marshalling" \
19-
" and unmarshalling event data."
14+
spec.description =
15+
"The official Ruby implementation of the CloudEvents Specification. " \
16+
"Provides data types for events, and HTTP/JSON bindings for marshalling " \
17+
"and unmarshalling event data."
2018
spec.homepage = "https://github.com/cloudevents/sdk-ruby"
2119

2220
spec.files = ::Dir.glob("lib/**/*.rb") + ::Dir.glob("*.md") + [".yardopts"]
2321
spec.require_paths = ["lib"]
24-
spec.required_ruby_version = ">= 2.5"
22+
spec.required_ruby_version = ">= 2.7"
2523

2624
if spec.respond_to? :metadata
2725
spec.metadata["changelog_uri"] = "https://cloudevents.github.io/sdk-ruby/v#{version}/file.CHANGELOG.html"

features/step_definitions/steps.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
end
1010

1111
Given "an HTTP request" do |str|
12+
# WEBrick parsing wants the lines delimited by \r\n, but the input
13+
# content-length assumes \n within the body.
14+
parts = str.split "\n\n"
15+
parts[0].gsub! "\n", "\r\n"
16+
str = "#{parts[0]}\r\n\r\n#{parts[1]}"
1217
webrick_request = WEBrick::HTTPRequest.new WEBrick::Config::HTTP
1318
webrick_request.parse StringIO.new str
1419
@rack_request = {}

lib/cloud_events/content_type.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def consume_token str, downcase: false, error_message: nil
152152

153153
def consume_special str, expected, error_message: nil
154154
raise ParseError, error_message || "Expected #{expected.inspect}" unless str.start_with? expected
155-
consume_comments str[1..-1].strip
155+
consume_comments str[1..].strip
156156
end
157157

158158
def consume_token_or_quoted str, error_message: nil
@@ -177,7 +177,7 @@ def consume_token_or_quoted str, error_message: nil
177177
end
178178
end
179179
index += 1
180-
str = consume_comments str[index..-1].strip
180+
str = consume_comments str[index..].strip
181181
[arr.join, str]
182182
end
183183

@@ -194,14 +194,14 @@ def consume_comments str
194194
when "\\"
195195
index += 2
196196
when "("
197-
str = consume_comments str[index..-1]
197+
str = consume_comments str[index..]
198198
index = 0
199199
else
200200
index += 1
201201
end
202202
end
203203
index += 1
204-
consume_comments str[index..-1].strip
204+
consume_comments str[index..].strip
205205
end
206206

207207
def maybe_quote str

lib/cloud_events/event/field_interpreter.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def string keys, required: false, allow_empty: false
3030
value.freeze
3131
[value, value]
3232
else
33-
raise AttributeError, "Illegal type for #{keys.first}:" \
34-
" String expected but #{value.class} found"
33+
raise AttributeError, "Illegal type for #{keys.first}: " \
34+
"String expected but #{value.class} found"
3535
end
3636
end
3737
end
@@ -49,8 +49,8 @@ def uri keys, required: false
4949
when ::URI::Generic
5050
[Utils.deep_freeze(value), value.to_s.freeze]
5151
else
52-
raise AttributeError, "Illegal type for #{keys.first}:" \
53-
" String or URI expected but #{value.class} found"
52+
raise AttributeError, "Illegal type for #{keys.first}: " \
53+
"String or URI expected but #{value.class} found"
5454
end
5555
end
5656
end
@@ -70,8 +70,8 @@ def rfc3339_date_time keys, required: false
7070
value = value.to_datetime
7171
[Utils.deep_freeze(value), value.rfc3339.freeze]
7272
else
73-
raise AttributeError, "Illegal type for #{keys.first}:" \
74-
" String, Time, or DateTime expected but #{value.class} found"
73+
raise AttributeError, "Illegal type for #{keys.first}: " \
74+
"String, Time, or DateTime expected but #{value.class} found"
7575
end
7676
end
7777
end
@@ -85,8 +85,8 @@ def content_type keys, required: false
8585
when ContentType
8686
[value, value.to_s]
8787
else
88-
raise AttributeError, "Illegal type for #{keys.first}:" \
89-
" String, or ContentType expected but #{value.class} found"
88+
raise AttributeError, "Illegal type for #{keys.first}: " \
89+
"String, or ContentType expected but #{value.class} found"
9090
end
9191
end
9292
end
@@ -99,8 +99,8 @@ def spec_version keys, accept:
9999
value.freeze
100100
[value, value]
101101
else
102-
raise AttributeError, "Illegal type for #{keys.first}:" \
103-
" String expected but #{value.class} found"
102+
raise AttributeError, "Illegal type for #{keys.first}: " \
103+
"String expected but #{value.class} found"
104104
end
105105
end
106106
end
@@ -121,7 +121,7 @@ def object keys, required: false, allow_nil: false
121121
keys.each do |key|
122122
key_present = @args.key? key
123123
val = @args.delete key
124-
value = val if allow_nil && key_present || !allow_nil && !val.nil?
124+
value = val if (allow_nil && key_present) || (!allow_nil && !val.nil?)
125125
end
126126
if value == UNDEFINED
127127
raise AttributeError, "The #{keys.first} field is required" if required

lib/cloud_events/event/opaque.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def == other
7373

7474
## @private
7575
def hash
76-
@content.hash ^ @content_type.hash ^ @batch.hash
76+
[@content, @content_type, @batch].hash
7777
end
7878
end
7979
end

lib/cloud_events/http_binding.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ def initialize
4646
end
4747
@event_encoders = {}
4848
@data_decoders = Format::Multi.new do |result|
49-
result&.key?(:data) && result&.key?(:content_type) ? result : nil
49+
result&.key?(:data) && result.key?(:content_type) ? result : nil
5050
end
5151
@data_encoders = Format::Multi.new do |result|
52-
result&.key?(:content) && result&.key?(:content_type) ? result : nil
52+
result&.key?(:content) && result.key?(:content_type) ? result : nil
5353
end
5454
text_format = TextFormat.new
5555
@data_decoders.formats.replace [text_format, DefaultDataFormat]
@@ -110,7 +110,7 @@ def register_formatter_methods formatter,
110110
@event_decoders.formats.unshift formatter if decode_event
111111
if encode_event
112112
encoders = @event_encoders[encode_event] ||= Format::Multi.new do |result|
113-
result&.key?(:content) && result&.key?(:content_type) ? result : nil
113+
result&.key?(:content) && result.key?(:content_type) ? result : nil
114114
end
115115
encoders.formats.unshift formatter
116116
end
@@ -325,7 +325,7 @@ def encode_binary_content event, legacy_data_encode: true, **format_args
325325
#
326326
def percent_decode str
327327
str = str.gsub(/"((?:[^"\\]|\\.)*)"/) { ::Regexp.last_match(1).gsub(/\\(.)/, '\1') }
328-
decoded_str = str.gsub(/%[0-9a-fA-F]{2}/) { |m| [m[1..-1].to_i(16)].pack "C" }
328+
decoded_str = str.gsub(/%[0-9a-fA-F]{2}/) { |m| [m[1..].to_i(16)].pack "C" }
329329
decoded_str.force_encoding ::Encoding::UTF_8
330330
end
331331

0 commit comments

Comments
 (0)