Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast boolean values #45

Merged
merged 11 commits into from
Dec 4, 2024
Merged

Cast boolean values #45

merged 11 commits into from
Dec 4, 2024

Conversation

i7an
Copy link
Contributor

@i7an i7an commented Nov 22, 2024

Boolean methods return raw values. AWS Parameters Store does not support boolean type.

Global.foo.enabled? # => "false"

if Global.foo.enabled? # "false" is truthy
  # ...
end

In this PR I attempted to address this problem:

Global.foo.enabled # => "false"
Global.foo.enabled.class # => String
Global.foo.enabled? # => false
Global.foo.enabled?.class # => FalseClass

require 'rubygems'
require 'bundler'

Bundler.require
Copy link
Contributor Author

Choose a reason for hiding this comment

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

https://bundler.io/guides/bundler_setup.html

For such a small Gemfile, we’d advise you to skip Bundler.require and just require the gems by hand

@@ -1,12 +1,7 @@
# frozen_string_literal: true

require 'rubygems'
require 'bundler'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did not find why these were needed.

@@ -95,7 +95,7 @@ def load_parameters_from_ssm(next_token = nil)
def build_configuration_from_parameters(parameters)
configuration = {}
parameters.each do |parameter|
parameter_parts = parameter.name[@prefix.length..-1].split(PATH_SEPARATOR).map(&:to_sym)
parameter_parts = parameter.name[@prefix.length..].split(PATH_SEPARATOR).map(&:to_sym)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

rubocop autofix. applies to other as well.

'off', :off,
'OFF', :OFF
].to_set.freeze
private_constant :FALSE_VALUES
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FALSE_VALUES is implementation details and should not be exposed.

normalized_method = normalize_key_by_method(method)
if key?(normalized_method)
value = get_configuration_value(normalized_method)
boolean_method?(method) ? cast_boolean(value) : value
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is what this PR is all about.

require 'aws-sdk-ssm'
require 'global/backend/aws_parameter_store'

RSpec.describe Global::Backend::AwsParameterStore do
subject(:parameter_store) do
described_class.new(prefix: '/testapp/', client: client)
end
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed rubocop abuses. applies to other spec files.

@@ -1,9 +1,5 @@
# frozen_string_literal: true

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

spec and lib directories are in the load path by default

@@ -1,9 +1,5 @@
# frozen_string_literal: true

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'rspec'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

rspec/core is loaded by default

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'rspec'
require 'global'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

simplecov should be required before any code is loaded
https://github.com/simplecov-ruby/simplecov?tab=readme-ov-file#troubleshooting

Copy link
Member

@leonid-shevtsov leonid-shevtsov left a comment

Choose a reason for hiding this comment

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

I suppose the ruby version range is acceptable, seeing as 3.0 is already EOL

- 3.3
- 3.2
- 3.1
- 3.0
Copy link
Contributor Author

Choose a reason for hiding this comment

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

image

Copy link
Member

@le0pard le0pard left a comment

Choose a reason for hiding this comment

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

need some fixes


Gem::Specification.new do |s|
s.name = 'global'
s.version = Global::VERSION
s.required_ruby_version = '>= 3.0.0'
Copy link
Member

Choose a reason for hiding this comment

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

This may require by semver release major version

s.summary = 'Simple way to load your configs from yaml/aws/gcp'

s.metadata['rubygems_mfa_required'] = 'true'
Copy link
Member

Choose a reason for hiding this comment

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

Not sure, we activated this and how ci will do release

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@le0pard could you please share the script that does the release? I want to check that.

Copy link
Member

Choose a reason for hiding this comment

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

Screenshot 2024-11-29 at 13 36 34

Copy link
Contributor Author

@i7an i7an Dec 3, 2024

Choose a reason for hiding this comment

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

how ci will do release

I assumed there is CI that pushed a new version automatically. Ok.
Could you please check if MFA is on or off? If not maybe we should turn it on?

@@ -61,6 +77,11 @@ def boolean_method?(method)
'?' == method.to_s[-1]
end

# @see ActiveModel::Type::Boolean#cast_value
def cast_boolean(value)
!FALSE_VALUES.include?(value)
Copy link
Member

Choose a reason for hiding this comment

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

so empty string will be true? should it be nil...

@@ -2,6 +2,6 @@

module Global

VERSION = '2.1.0'
VERSION = '2.2.0'
Copy link
Member

Choose a reason for hiding this comment

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

nope, new major version - removed ruby 2 support


it 'reads parameters from the parameter store' do
it 'reads parameters from the parameter store' do # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
Copy link
Member

Choose a reason for hiding this comment

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

RSpec/MultipleExpectations - you can fix this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried several options. next_token expectations is the tricky part. If you want to keep them, you have to adjust rubocop configuration. To reduce the number of lines again you have to deal with next_token expectations, move stubs to elsewhere which does not improve code readability.
At the end I think disabling those two rules for one it is fine. If you disagree please suggest how to deal with these offences.

{
'key' => 'value',
'boolean_key' => true,
'string_boolean_key' => '1',
Copy link
Member

Choose a reason for hiding this comment

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

test with empty string and false value

subject(:global) { described_class }

describe 'merging backends' do
# rubocop:disable RSpec/VerifiedDoubles
Copy link
Member

Choose a reason for hiding this comment

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

this can be fixed and written correctly

Copy link
Contributor Author

@i7an i7an Nov 29, 2024

Choose a reason for hiding this comment

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

Global takes an object that quacks like a configuration. This spec tests merging, thus abstract doubles are legit.


@not_match_item = double
allow(@not_match_item).to receive(:name).and_return('different_key')
secret_data = double(data: 'secret value')
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤷‍♂️

Google::Cloud::SecretManager::V1::SecretPayload.new.data
# => ""
instance_double(Google::Cloud::SecretManager::V1::SecretPayload, data: 'secret value')
# => RSpec::Mocks::MockExpectationError: class does not implement the instance method: data

@i7an i7an requested a review from le0pard December 4, 2024 10:16
@le0pard le0pard merged commit 2d442e3 into railsware:master Dec 4, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants