Skip to content
Closed
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
11 changes: 11 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ jobs:
- run: bundle install
- name: Rubocop
run: bundle exec rubocop --color
steep:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josecolella @technicalpickles Thoughts on enforcing this check on CI if we're going to start supporting RBS?

runs-on: ubuntu-latest
name: Steep
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2
- run: bundle install
- name: Steep
run: bundle exec steep check
# check the status of other jobs, so we can have a single job dependency for branch protection
# https://github.com/community/community/discussions/4324#discussioncomment-3477871
status:
Expand Down
44 changes: 44 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,38 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activesupport (7.0.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
ast (2.4.2)
concurrent-ruby (1.2.2)
csv (3.2.7)
diff-lcs (1.5.0)
ffi (1.15.5)
ffi (1.15.5-x64-mingw-ucrt)
ffi (1.15.5-x64-mingw32)
fileutils (1.7.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
json (2.6.2)
language_server-protocol (3.17.0.3)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.5.3)
markly (0.7.0)
minitest (5.20.0)
parallel (1.22.1)
parser (3.1.2.1)
ast (~> 2.4.1)
rainbow (3.1.1)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rbs (3.2.1)
regexp_parser (2.6.0)
rexml (3.2.5)
rspec (3.12.0)
Expand Down Expand Up @@ -44,6 +66,27 @@ GEM
rubocop-ast (1.23.0)
parser (>= 3.1.1.0)
ruby-progressbar (1.11.0)
securerandom (0.2.2)
steep (1.5.3)
activesupport (>= 5.1)
concurrent-ruby (>= 1.1.10)
csv (>= 3.0.9)
fileutils (>= 1.1.0)
json (>= 2.1.0)
language_server-protocol (>= 3.15, < 4.0)
listen (~> 3.0)
logger (>= 1.3.0)
parser (>= 3.1)
rainbow (>= 2.2.2, < 4.0)
rbs (>= 3.1.0)
securerandom (>= 0.1)
strscan (>= 1.0.0)
terminal-table (>= 2, < 4)
strscan (3.0.6)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.3.0)

PLATFORMS
Expand All @@ -63,6 +106,7 @@ DEPENDENCIES
rake (~> 13.0)
rspec (~> 3.12.0)
rubocop (~> 1.37.1)
steep (~> 1.5.0)

BUNDLED WITH
2.3.25
10 changes: 10 additions & 0 deletions Steepfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

target :lib do
signature "sig"
check "lib"
library "pathname"
library "forwardable"
library "singleton"
library "uri"
end
2 changes: 1 addition & 1 deletion lib/openfeature/sdk/metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def initialize(name:, version: nil)
end

def ==(other)
raise ArgumentError("Expected comparison to be between Metadata object") unless other.is_a?(Metadata)
raise ArgumentError, "Expected comparison to be between Metadata object" unless other.is_a?(Metadata)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unrelated to the RBS changes. Did we pick up a new Rubocop rule?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it's actually steep complaining.

lib/openfeature/sdk/metadata.rb:29:14: [error] Type `::OpenFeature::SDK::Metadata` does not have method `ArgumentError`
│ Diagnostic ID: Ruby::NoMethod
│
└         raise ArgumentError("Expected comparison to be between Metadata object") unless other.is_a?(Metadata)
                ~~~~~~~~~~~~~

Looking at the documentation for Kernel::raise it kind of makes sense. TIL, they are pretty clear about how thet expect raise to be used when setting an error_message.


@name == other.name && @version == other.version
end
Expand Down
1 change: 1 addition & 0 deletions openfeature-sdk.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.12.0"
spec.add_development_dependency "rubocop", "~> 1.37.1"
spec.add_development_dependency "steep", "~> 1.5.0"
end
4 changes: 2 additions & 2 deletions sig/openfeature/sdk.rbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Openfeature
module Sdk
module OpenFeature
module SDK
VERSION: String
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
end
Expand Down
31 changes: 31 additions & 0 deletions sig/openfeature/sdk/_hook.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
type flagValue = bool | Numeric | String | Hash[String, untyped]
type flagValueType = :bool | :integer | :float | :string | :object
type evaluationContext = { targeting_key: String? }
type evaluationDetails = { flag_key: String, flag_value?: flagValue }

type hookContext[T] = {
flag_key: String,
flag_value_type: flagValueType,
evaluation_context: evaluationContext,
default_value: T,
}

type hookHints = Hash[String, flagValue]

interface _BeforeHook
def before: (evaluationContext, ?hookHints) -> (evaluationContext | void)
end

interface _AfterHook[T]
def after: (hookContext[T], evaluationDetails, ?hookHints) -> void
end

interface _ErrorHook[T]
def error: (hookContext[T], Exception, ?hookHints) -> void
end

interface _FinallyHook[T]
def finally: (hookContext[T], ?hookHints) -> void
end

type hook = _BeforeHook | _AfterHook[flagValue] | _ErrorHook[flagValue] | _FinallyHook[flagValue]
22 changes: 22 additions & 0 deletions sig/openfeature/sdk/api.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module OpenFeature
module SDK

interface _Configuration
def context: () -> void
end

class API
include _Configuration
extend Forwardable

attr_reader configuration: Configuration

def build_client: -> Client

def configure: () { (Configuration) -> void } -> void

# Singleton's RBS doesn't quite work
def self.instance: () -> instance
end
end
end
17 changes: 17 additions & 0 deletions sig/openfeature/sdk/client.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module OpenFeature
module SDK
class Client
RESULT_TYPE: Array[Symbol]
SUFFIXES: Array[Symbol]

@context: evaluationContext
@hooks: Array[hook]

attr_accessor hooks: Array[hook]
attr_reader metadata: Metadata?
attr_reader provider: untyped

def initialize: (provider: untyped , client_options: untyped, context: untyped) -> void
end
end
end
19 changes: 19 additions & 0 deletions sig/openfeature/sdk/configuration.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

module Concurrent
class Array[T] < ::Array[T]
def initialize: (?::Array[T]) -> void
end
end

module OpenFeature
module SDK
class Configuration
extend Forwardable

attr_accessor context: evaluationContext
attr_accessor hooks: [hook]
attr_accessor metadata: Metadata
attr_accessor provider: untyped
end
end
end
12 changes: 12 additions & 0 deletions sig/openfeature/sdk/metadata.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module OpenFeature
module SDK
class Metadata
attr_reader name: String
attr_reader version: String?

def initialize: (name: String, ?version: String?) -> void

def ==: (untyped other) -> untyped
end
end
end
30 changes: 30 additions & 0 deletions sig/openfeature/sdk/provider/no_op_provider.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module OpenFeature
module SDK
module Provider
class NoOpProvider
REASON_NO_OP: String
NAME: String
class ResolutionDetails[T] < ::Struct[T]
def initialize : (value: T, reason: String) -> void

attr_reader value(): T
attr_reader reason(): untyped
attr_reader variant(): untyped
attr_reader error_code(): untyped
attr_reader error_message(): untyped
end

attr_reader metadata: Metadata

def fetch_boolean_value: (flag_key: String, default_value: bool, ?evaluation_context: evaluationContext?) -> ResolutionDetails[bool]

def fetch_string_value: (flag_key: String, default_value: String, ?evaluation_context: evaluationContext?) -> ResolutionDetails[String]

def fetch_number_value: (flag_key: String, default_value: Numeric, ?evaluation_context: evaluationContext?) -> ResolutionDetails[Numeric]

def fetch_object_value: (flag_key: String, default_value: Hash[String|Symbol, untyped], ?evaluation_context: evaluationContext?) -> ResolutionDetails[Hash[String|Symbol, untyped]]
def no_op: [X] (X) -> ResolutionDetails[X]
end
end
end
end