biran 0.1.13.1 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec150cd74d08598ecb7d3bfb1324bf57c15e20806c0143b042b257569f430bf6
4
- data.tar.gz: 7863cf3face519ede43bb1ca24f569112ad83fe8e686c467141c81a13a0b981d
3
+ metadata.gz: 1175961da6d05c7c7b23697b7522f2eebfbcee12fdf62cee19cee89dc1cd9ff0
4
+ data.tar.gz: e1b32e766224708ef485e81cf535ab0011e78dd97382f655fb358174ffd6e7f2
5
5
  SHA512:
6
- metadata.gz: 5464720ba0f9989e9941b77ca1fd54a17388eedd3d044e180689ce58fb7a1da87252e0ccfa09fab514410077ffe18b0a7fbbb52a56a35fce0ebc8ed6b5fb4964
7
- data.tar.gz: 1edb42ac1ebc49f45d6c60e312a4bd089495fdc11c2c96be0f1f2328f4a8d6bbdb5d14b11dbfe16fae34b8c1ab086b6ee48c82bfe4d0c3d0e8a0400e73a4b907
6
+ metadata.gz: 6ba45896793d88333fcc70fd22e5886293c46beb8e7eca1ae7ab250ccab510af4014e7dbe42a67453a7f009de0e1b01826f9d152b1a628bbce958eb961785fec
7
+ data.tar.gz: 6b3676949fec3f902e8cbb5fd3fd8cae359cd3b88bf3026b71a1c97a300b4ff2d101c1de44c615089aab7383d6c21afbce30d290fdf9011d4ab1603154428bea
data/README.md CHANGED
@@ -40,7 +40,8 @@ Dir.glob('lib/tasks/*.rake').each {|r| import r}
40
40
  # Configuration
41
41
 
42
42
  You can set where your config files are, rails end and other stuff in a file like `config/initializers/biran.rb`
43
- You can also set options in `config/app_config.yml` in the `app` block. This list will be loaded last and override anything set in the initializer.
43
+ You can also set options in `config/app_config.yml` in the `app` block. This list will be loaded last and override anything set in the initializer. All string
44
+ input is sanitized to remove special characters that don't play well with file system paths. Any special haracters found are replaced with a '-'.
44
45
 
45
46
  Config file example:
46
47
  ```
@@ -92,6 +93,7 @@ the list of things you can configure are:
92
93
  :local_config_filename,
93
94
  :db_config_file_name,
94
95
  :secrets_filename,
96
+ :extra_config_suffix,
95
97
  :config_dirname,
96
98
  :base_path,
97
99
  :shared_dir,
@@ -145,6 +147,16 @@ Available in: config file, initializer**
145
147
 
146
148
  Generally no need to change, but here in case you want to. Default is `secrets.yml`
147
149
 
150
+ ### extra_config_suffix
151
+ **Type: string
152
+ Default: extras
153
+ Available in: environment variable, config_file, initializer**
154
+
155
+ Sets the suffix to be applied to an extra config file you may want to load. The suffix is appended to the value of the config_filename. The default value will be `app_config_extras.yml`.
156
+ This file gets loaded just before the local config file and can be used to provide additional configuration based stored in a second file. There are times when you may want to organize the
157
+ configuration based on sub grouping that the yaml just doesn't allow easily.
158
+ Use cases might include grouping config based on a location, type of host, or even for testing purposes.
159
+
148
160
  ### config_dirname
149
161
  **Type: string
150
162
  Default: config
data/Rakefile CHANGED
@@ -22,10 +22,10 @@ begin
22
22
  task("spec").clear
23
23
 
24
24
  RSpec::Core::RakeTask.new(:spec) do |t|
25
- t.rspec_opts = "--format RSpec::TapY | tapout runtime"
25
+ t.rspec_opts = "--format documentation"
26
26
  end
27
27
 
28
- task :default => :spec
28
+ task default: :spec
29
29
  rescue LoadError
30
30
  raise 'No rspec available'
31
31
  end
@@ -5,9 +5,24 @@ defaults: &defaults
5
5
  files_to_generate:
6
6
  my_config:
7
7
  extension: '.yml'
8
+ my_first_value: 1
9
+ my_second_value: 2
10
+ my_fifth_value: 5
11
+ nested_values: &nested_defaults
12
+ my_third_value: 3
13
+ my_fourth_value: 4
14
+ my_sixth_value: 6
8
15
 
9
16
  test:
10
17
  <<: *defaults
18
+ my_first_value: 11
19
+ nested_values:
20
+ <<: *nested_defaults
21
+ my_third_value: 13
11
22
 
12
23
  development:
13
24
  <<: *defaults
25
+ my_first_value: 11
26
+ nested_values:
27
+ <<: *nested_defaults
28
+ my_third_value: 13
@@ -0,0 +1,10 @@
1
+ defaults: &defaults
2
+ my_fifth_value: 55
3
+ nested_values:
4
+ my_sixth_value: 66
5
+
6
+ development:
7
+ <<: *defaults
8
+
9
+ test:
10
+ <<: *defaults
data/lib/biran/config.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'singleton'
2
3
 
3
4
  module Biran
@@ -6,14 +7,15 @@ module Biran
6
7
 
7
8
  attr_writer :config_filename, :local_config_filename, :db_config_filename,
8
9
  :secrets_filename, :config_dirname, :use_capistrano, :db_config,
9
- :secrets, :base_path, :app_env, :base_dir, :bindings, :app_setup_blocks
10
+ :secrets, :base_path, :app_env, :base_dir, :bindings, :app_setup_blocks,
11
+ :extra_config_suffix
10
12
 
11
13
  attr_accessor :shared_dir
12
14
 
13
15
  def app_env
14
16
  return @app_env if @app_env
15
17
  @app_env = Rails.env if defined? Rails
16
- @app_env ||= 'development'.freeze
18
+ @app_env ||= 'development'
17
19
  end
18
20
 
19
21
  def base_dir
@@ -21,27 +23,27 @@ module Biran
21
23
  end
22
24
 
23
25
  def config_filename
24
- @config_filename ||= 'app_config.yml'.freeze
26
+ @config_filename ||= 'app_config.yml'
25
27
  end
26
28
 
27
29
  def local_config_filename
28
- @local_config_filename ||= 'local_config.yml'.freeze
30
+ @local_config_filename ||= 'local_config.yml'
29
31
  end
30
32
 
31
33
  def db_config_filename
32
- @db_config_filename ||= 'db_config.yml'.freeze
34
+ @db_config_filename ||= 'db_config.yml'
33
35
  end
34
36
 
35
37
  def secrets_filename
36
- @secrets_filename ||= 'secrets.yml'.freeze
38
+ @secrets_filename ||= 'secrets.yml'
37
39
  end
38
40
 
39
41
  def config_dirname
40
- @config_dirname ||= 'config'.freeze
42
+ @config_dirname ||= 'config'
41
43
  end
42
44
 
43
45
  def vhost_public_dirname
44
- @vhost_public_dirname ||= 'public'.freeze
46
+ @vhost_public_dirname ||= 'public'
45
47
  end
46
48
 
47
49
  def use_capistrano
@@ -63,13 +65,17 @@ module Biran
63
65
  end
64
66
 
65
67
  def app_setup_blocks
66
- @app_setup_blocks ||= %i[app].freeze
68
+ @app_setup_blocks ||= %i[app]
67
69
  end
68
70
 
69
71
  def bindings
70
72
  @bindings ||= %i[db_config]
71
73
  end
72
74
 
75
+ def extra_config_suffix
76
+ @extra_config_suffix ||= 'extras'
77
+ end
78
+
73
79
  def base_path
74
80
  return @base_path if @base_path
75
81
  @base_path = Rails.root if defined? Rails
@@ -20,7 +20,8 @@ module Biran
20
20
  end
21
21
 
22
22
  def app_env
23
- ENV['BIRAN_APP_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || configuration.app_env
23
+ app_env = ENV['BIRAN_APP_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || configuration.app_env
24
+ sanitize_input(app_env)
24
25
  end
25
26
 
26
27
  def app_base
@@ -41,37 +42,62 @@ module Biran
41
42
  app_config_defaults[:app][:bindings]
42
43
  end
43
44
 
45
+ def config_dirname
46
+ sanitize_input(configuration.config_dirname)
47
+ end
48
+
44
49
  def config_dir
45
- File.join configuration.base_path, configuration.config_dirname
50
+ File.join(configuration.base_path, config_dirname)
46
51
  end
47
52
 
48
53
  def local_config_file
49
54
  ENV['BIRAN_LOCAL_CONFIG_FILE'] ||
50
- File.join(app_shared_dir, configuration.config_dirname, local_config_filename)
55
+ File.join(app_shared_dir, config_dirname, local_config_filename)
51
56
  end
52
57
 
53
58
  def local_config_filename
54
- ENV['BIRAN_LOCAL_CONFIG_FILENAME'] || app_config_defaults[:app][:local_config_filename] || configuration.local_config_filename
59
+ filename= ENV['BIRAN_LOCAL_CONFIG_FILENAME'] || app_config_defaults[:app][:local_config_filename] || configuration.local_config_filename
60
+ sanitize_input( filename )
61
+ end
62
+
63
+ def extra_config_suffix
64
+ suffix = ENV['BIRAN_EXTRA_CONFIG_SUFFIX'] || app_config_defaults[:app][:extra_config_suffix] || configuration.extra_config_suffix
65
+ sanitize_input( suffix )
66
+ end
67
+
68
+ def extra_config_file
69
+ File.join(config_dirname, app_config_filename.gsub(/\.yml$/, "_#{extra_config_suffix}.yml"))
70
+ end
71
+
72
+ def app_config_filename
73
+ sanitize_input(configuration.config_filename)
74
+ end
75
+
76
+ def app_config_file
77
+ File.join(config_dirname, app_config_filename)
55
78
  end
56
79
 
57
80
  def vhost_public_dirname
58
- ENV['BIRAN_VHOST_PUBLIC_DIRNAME'] || app_config_defaults[:app][:vhost_public_dirname]
81
+ pub_dir_name = ENV['BIRAN_VHOST_PUBLIC_DIRNAME'] || app_config_defaults[:app][:vhost_public_dirname]
82
+ sanitize_input(pub_dir_name)
59
83
  end
60
84
 
61
85
  def db_config_override_file
62
- File.join(app_shared_dir, configuration.config_dirname, db_config_filename)
86
+ File.join(app_shared_dir, config_dirname, db_config_filename)
63
87
  end
64
88
 
65
89
  def db_config_filename
66
- app_config_defaults[:app][:db_config_filename] || configuration.db_config_filename
90
+ filename = app_config_defaults[:app][:db_config_filename] || configuration.db_config_filename
91
+ sanitize_input(filename)
67
92
  end
68
93
 
69
94
  def secrets_file
70
- File.join(configuration.base_path, configuration.config_dirname, secrets_filename)
95
+ File.join(configuration.base_path, config_dirname, secrets_filename)
71
96
  end
72
97
 
73
98
  def secrets_filename
74
- app_config_defaults[:app][:secrets_filename] || configuration.secrets_filename
99
+ filename = app_config_defaults[:app][:secrets_filename] || configuration.secrets_filename
100
+ sanitize_input(filename)
75
101
  end
76
102
 
77
103
  def default_db_config_file
@@ -81,5 +107,10 @@ module Biran
81
107
  def use_capistrano?
82
108
  # Implement in consumer class
83
109
  end
110
+
111
+ def sanitize_input string
112
+ # Borrowed from ActiveStorage
113
+ string.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "�").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-")
114
+ end
84
115
  end
85
116
  end
@@ -61,6 +61,7 @@ module Biran
61
61
  app_config[:secrets].deep_merge! get_secrets_content(app_config[:secrets_file_path])
62
62
  app_config[:db_config].deep_merge! build_db_config
63
63
 
64
+ app_config.deep_merge! extra_config_file_contents
64
65
  app_config.deep_merge! local_config_file_contents
65
66
  end
66
67
 
@@ -78,7 +79,6 @@ module Biran
78
79
 
79
80
  def app_config_defaults
80
81
  return @app_config_defaults if @app_config_defaults
81
- app_config_file = File.join(configuration.config_dirname, configuration.config_filename)
82
82
  app_defaults = app_defaults_init.dup
83
83
  config_properties = process_config_file(app_config_file)
84
84
  @app_config_defaults = app_defaults.deep_merge! config_properties
@@ -87,7 +87,7 @@ module Biran
87
87
  def process_config_file(config_file)
88
88
  config_file_contents = File.read(config_file)
89
89
  config_file_contents = ERB.new(config_file_contents).result
90
- config_file_contents = YAML.safe_load(config_file_contents, [], [], true)
90
+ config_file_contents = yaml_load(config_file_contents)
91
91
  config_file_contents[env].deep_symbolize_keys!
92
92
  rescue Errno::ENOENT
93
93
  raise "Missing config file: #{config_file}"
@@ -113,6 +113,12 @@ module Biran
113
113
  process_config_file secrets_file
114
114
  end
115
115
 
116
+ def extra_config_file_contents
117
+ return @extra_config_contents if @extra_config_contents
118
+ return @extra_config_contents = {} unless File.exists? extra_config_file
119
+ @extra_config_contents = process_config_file(extra_config_file)
120
+ end
121
+
116
122
  def sanitize_config_files files_list
117
123
  lambda do |(file, _)|
118
124
  files_list[file] ||= {extension: ''}
@@ -122,6 +128,11 @@ module Biran
122
128
  end
123
129
  end
124
130
 
131
+ def yaml_load data_content
132
+ # Ruby 3.1 with Psych 4 allows yaml-aliases only in direct manner
133
+ YAML.safe_load(data_content, aliases: true)
134
+ end
135
+
125
136
  def filtered_config
126
137
  @filtered_config ||= config.except(*configuration.app_setup_blocks)
127
138
  end
@@ -0,0 +1,155 @@
1
+ require 'biran/hash_refinement'
2
+
3
+ module Biran
4
+ class Configurinator
5
+ include ConfigDefaults
6
+ using HashRefinement
7
+
8
+ DEFAULT_ENV = 'development'
9
+
10
+ attr_reader :config, :db_config, :env
11
+
12
+ class << self
13
+ attr_accessor :config
14
+
15
+ def configure
16
+ self.config ||= Config.instance
17
+ yield config
18
+ end
19
+ end
20
+
21
+ def initialize(env: nil)
22
+ @env = env || app_env
23
+ @config = build_app_config
24
+ end
25
+
26
+ def file_tasks
27
+ files_to_generate.keys
28
+ end
29
+
30
+ def files_to_generate
31
+ @files_to_generate ||= config.fetch(:app, {})
32
+ .fetch(:files_to_generate, configuration.files_to_generate)
33
+ .tap { |files_list| files_list.each(&sanitize_config_files(files_list)) }
34
+ end
35
+
36
+ def create(name:, extension:, output_dir: nil, output_name: nil)
37
+ output_dir ||= config_dir
38
+ output_name ||= name
39
+ generated_file = ERBConfig.new(filtered_config, name, extension, config_dir, output_dir, output_name)
40
+ generated_file.bindings = bindings
41
+ generated_file.save!
42
+ end
43
+
44
+ private
45
+
46
+ def build_app_config
47
+ raise 'Environment not set to build the application config' unless @env
48
+ app_config = {
49
+ app_root_dir: app_root,
50
+ app_shared_dir: app_shared_dir,
51
+ app_base_dir: app_base,
52
+ env: env,
53
+ local_config_file: local_config_file,
54
+ secrets_file_path: secrets_file,
55
+ vhost: config_vhost_dirs
56
+ }
57
+
58
+ app_config.deep_merge! app_config_defaults
59
+ app_config[:secrets].deep_merge! get_secret_contents(app_config)
60
+ app_config[:db_config] = build_db_config
61
+
62
+ app_config.deep_merge! local_config_file_contents
63
+
64
+ puts "app config final is #{app_config.inspect}"
65
+ app_config
66
+ end
67
+
68
+ def build_db_config
69
+ default_db_config = base_db_config
70
+ return default_db_config unless File.exist? db_config_override_file
71
+ default_db_config.deep_merge! process_config_file(db_config_override_file)
72
+ end
73
+
74
+ def base_db_config
75
+ return @base_db_config if @base_db_config
76
+ return @base_db_config = {} unless File.exists? default_db_config_file
77
+ @base_db_config ||= process_config_file(default_db_config_file)
78
+ end
79
+
80
+ def app_config_defaults
81
+ return @app_config_defaults if @app_config_defaults
82
+ app_config_file = File.join(configuration.config_dirname, configuration.config_filename)
83
+ app_defaults = app_defaults_init.dup
84
+ config_properties = process_config_file(app_config_file)
85
+ @app_config_defaults = app_defaults.deep_merge! config_properties
86
+ end
87
+
88
+ def process_config_file(config_file)
89
+ config_file_contents = File.read(config_file)
90
+ config_file_contents = ERB.new(config_file_contents).result
91
+ config_file_contents = YAML.safe_load(config_file_contents, [], [], true)
92
+ #puts "Config file contents after yaml load before env grab #{config_file_contents.inspect}"
93
+ config_file_contents_for_test = config_file_contents['test']
94
+ config_file_contents_for_env = config_file_contents[env]
95
+ puts "Config file contents for test:"
96
+ puts config_file_contents_for_test.to_yaml
97
+ puts
98
+ puts "Config file contents for #{env}:"
99
+ puts config_file_contents_for_env.to_yaml
100
+ puts
101
+ config_file_diff = config_file_contents_for_test.deep_diff(config_file_contents_for_env)
102
+ puts "diff hash is:"
103
+ puts config_file_diff.to_yaml
104
+ puts
105
+ config_file_diff_r = config_file_contents_for_env.deep_diff(config_file_contents_for_test)
106
+ puts "diff hash reversed is:"
107
+ puts config_file_diff_r.to_yaml
108
+ puts
109
+
110
+ config_file_contents_for_env.deep_symbolize_keys!
111
+ rescue Errno::ENOENT
112
+ raise "Missing config file: #{config_file}"
113
+ end
114
+
115
+ def config_vhost_dirs
116
+ {
117
+ public_dir: File.join(app_root, vhost_public_dirname),
118
+ shared_dir: app_shared_dir.to_s,
119
+ log_dir: File.join(app_root, 'log'),
120
+ pids_dir: File.join(app_root, 'tmp', 'pids')
121
+ }
122
+ end
123
+
124
+ def local_config_file_contents
125
+ return @local_config_contents if @local_config_contents
126
+ return @local_config_conents = {} unless File.exists? local_config_file
127
+ @local_config_contents = process_config_file(local_config_file)
128
+ end
129
+
130
+ def get_secret_contents(app_config)
131
+ secrets_file_contents = {}
132
+ if File.exist? app_config[:secrets_file_path]
133
+ secrets_file_contents = process_config_file app_config[:secrets_file_path]
134
+ end
135
+ secrets_file_contents
136
+ end
137
+
138
+ def sanitize_config_files files_list
139
+ lambda do |file, _|
140
+ files_list[file] ||= {extension: ''}
141
+ ext = files_list[file].fetch(:extension, '').strip
142
+ ext.prepend('.') unless ext.start_with?('.') || ext.empty?
143
+ files_list[file][:extension] = ext
144
+ end
145
+ end
146
+
147
+ def filtered_config
148
+ @filtered_config ||= config.except(*configuration.app_setup_blocks)
149
+ end
150
+
151
+ def use_capistrano?
152
+ app_config_defaults[:app][:use_capistrano]
153
+ end
154
+ end
155
+ end
@@ -41,7 +41,7 @@ module Biran
41
41
 
42
42
  def process_erb
43
43
  config_erb_file = File.join(source_dir, "_#{name}#{extension}.erb")
44
- ERB.new(File.read(config_erb_file), nil, '-')
44
+ ERB.new(File.read(config_erb_file), trim_mode: '-')
45
45
  rescue Errno::ENOENT
46
46
  raise Biran::ConfigSyntaxError, "Missing template file for #{name}: #{config_erb_file}"
47
47
  end
@@ -0,0 +1,19 @@
1
+ module HashRefinement
2
+
3
+ refine Hash do
4
+ def deep_diff(b)
5
+ a = self
6
+ (a.keys | b.keys).inject({}) do |diff, k|
7
+ if a[k] != b[k]
8
+ if a[k].respond_to?(:deep_diff) && b[k].respond_to?(:deep_diff)
9
+ diff[k] = a[k].deep_diff(b[k])
10
+ else
11
+ #diff[k] = b[k] || a[k]
12
+ diff[k] = b.keys.exclude?(k) ? a[k] : b[k]
13
+ end
14
+ end
15
+ diff
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/biran/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Biran
2
- VERSION = '0.1.13.1'
2
+ VERSION = '0.1.15'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: biran
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13.1
4
+ version: 0.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - javierg
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-03-18 00:00:00.000000000 Z
13
+ date: 2023-04-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: railties
@@ -88,34 +88,6 @@ dependencies:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
90
  version: '3.7'
91
- - !ruby/object:Gem::Dependency
92
- name: tapout
93
- requirement: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - "~>"
96
- - !ruby/object:Gem::Version
97
- version: '0.4'
98
- type: :development
99
- prerelease: false
100
- version_requirements: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - "~>"
103
- - !ruby/object:Gem::Version
104
- version: '0.4'
105
- - !ruby/object:Gem::Dependency
106
- name: rspec-ontap
107
- requirement: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - "~>"
110
- - !ruby/object:Gem::Version
111
- version: '0.3'
112
- type: :development
113
- prerelease: false
114
- version_requirements: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - "~>"
117
- - !ruby/object:Gem::Version
118
- version: '0.3'
119
91
  description: Biran is the guy that will help you generate config files for your rail
120
92
  app.
121
93
  email:
@@ -129,19 +101,23 @@ files:
129
101
  - Rakefile
130
102
  - config/_my_config.yml.erb
131
103
  - config/app_config.yml
104
+ - config/app_config_test.yml
132
105
  - lib/biran.rb
133
106
  - lib/biran/config.rb
134
107
  - lib/biran/config_defaults.rb
135
108
  - lib/biran/configurinator.rb
109
+ - lib/biran/configurinator.rb.test_changes
136
110
  - lib/biran/erb_config.rb
137
111
  - lib/biran/exceptions.rb
112
+ - lib/biran/hash_refinement.rb
138
113
  - lib/biran/railtie.rb
139
114
  - lib/biran/version.rb
140
115
  - lib/tasks/biran_tasks.rake
141
116
  homepage: https://github.com/amco/biran
142
117
  licenses:
143
118
  - MIT
144
- metadata: {}
119
+ metadata:
120
+ rubygems_mfa_required: 'true'
145
121
  post_install_message:
146
122
  rdoc_options: []
147
123
  require_paths:
@@ -150,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
150
126
  requirements:
151
127
  - - ">="
152
128
  - !ruby/object:Gem::Version
153
- version: '0'
129
+ version: 2.6.0
154
130
  required_rubygems_version: !ruby/object:Gem::Requirement
155
131
  requirements:
156
132
  - - ">="