figjam 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ef230ae6ec36d15a5f04e18d1161544166313f02919d5174ef4a73fc6fae38e2
4
+ data.tar.gz: b75eef364afba9fe6d50f8ccc1bb4e3cc1c10e13a8dd7a351dc14cddbaa16e46
5
+ SHA512:
6
+ metadata.gz: a865580ea79bef3ff770573f20d7b6d3a66f97eb9eb8e526201342973c80e9fa8307640298e2dd29825656b6e77c65f9ed0998f64bf976f926d30c4558ad17f8
7
+ data.tar.gz: 3b6b0196e4fe1a80e18e9232764133c29ff4a323fd2bd864a94cf1390c796b87ad049dce634b7494d264523fadba4ec38a1eabae279c1cd235859b0fde90e7e2
data/README.md ADDED
@@ -0,0 +1,184 @@
1
+ figjam
2
+ ================
3
+
4
+ Figjam makes it easy to configure ruby and Rails apps `ENV` values by just using a single YAML file.
5
+
6
+ PRs to applications often need to come with default configuration values, but hardcoding these into
7
+ software makes them impossible to change at runtime. However supplying them separately to an
8
+ orchestration framework introduces deploy coordination that can be tricky to get right.
9
+
10
+ Figjam encourages you to commit default ENV values to a yaml file in your PRs. These are then
11
+ loaded at runtime, but, crucially, can be overridden at any time by supplying a real ENV. This
12
+ brings the ease of PR creation with the flexibility of runtime ENV changes.
13
+
14
+
15
+ ### Usage
16
+
17
+ Add Figjam to your Gemfile and `bundle install`:
18
+
19
+ ```ruby
20
+ gem "figjam"
21
+ ```
22
+
23
+ Then:
24
+
25
+ ```bash
26
+ $ bundle exec figjam install
27
+ ```
28
+
29
+ This creates a commented `config/application.yml` file which you can add default ENV to.
30
+ Add your own configuration to this file for all environments, and any specific environment
31
+ overrides.
32
+
33
+ ### Example
34
+
35
+ Given the following configuration file, the default value at the top will be used unless
36
+ RAILS_ENV matches any of the subsequent keys (like `test`, `prelive`, `produciton`).
37
+
38
+ ```yaml
39
+ # config/application.yml
40
+
41
+ GOOGLE_TAG_MANAGER_ID: GTM-12345
42
+
43
+ test:
44
+ # Use ~ for "nil"
45
+ GOOGLE_TAG_MANAGER_ID: ~
46
+
47
+ prelive:
48
+ GOOGLE_TAG_MANAGER_ID: GTM-45678
49
+
50
+ production:
51
+ GOOGLE_TAG_MANAGER_ID: GTM-98765
52
+ ```
53
+
54
+ You can then use those values in your app in an initializer, or in any other ruby code.
55
+
56
+ eg:
57
+ ```
58
+ # app/views/layouts/application.html.erb
59
+
60
+ <script>
61
+ var gtm_id = <%= ENV.fetch("GOOGLE_TAG_MANAGER_ID") %>
62
+ </script>
63
+ ```
64
+
65
+ Note, secrets are not to be provided by figjam, so do not add them to your `application.yml`.
66
+
67
+ **Please note:** `ENV` is a simple key/value store. All values will be converted
68
+ to strings. Deeply nested configuration structures are not possible.
69
+
70
+ ### Using `Figjam.env`
71
+
72
+ `Figjam.env` is a convenience that acts as a proxy to `ENV`.
73
+
74
+ In testing, it is sometimes more convenient to stub and unstub `Figjam.env` than
75
+ to set and reset `ENV`. Whether your application uses `ENV` or `Figjam.env` is
76
+ entirely a matter of personal preference.
77
+
78
+ ```yaml
79
+ # config/application.yml
80
+
81
+ GOOGLE_TAG_MANAGER_ID: "GTM-456789"
82
+ ```
83
+
84
+ ```ruby
85
+ ENV["GOOGLE_TAG_MANAGER_ID"] # => "GTM-456789"
86
+ ENV.key?("GOOGLE_TAG_MANAGER_ID") # => true
87
+ ENV["SOMETHING_ELSE"] # => nil
88
+ ENV.key?("SOMETHING_ELSE") # => false
89
+
90
+ Figjam.env.google_tag_manager_id # => "GTM-456789"
91
+ Figjam.env.google_tag_manager_id? # => true
92
+ Figjam.env.something_else # => nil
93
+ Figjam.env.something_else? # => false
94
+ ```
95
+
96
+ ### Required Keys
97
+
98
+ If a particular configuration value is required but not set, it's appropriate to
99
+ raise an error. With Figjam, you can either raise these errors proactively or
100
+ lazily.
101
+
102
+ To proactively require configuration keys:
103
+
104
+ ```ruby
105
+ # config/initializers/figjam.rb
106
+
107
+ Figjam.require_keys("GOOGLE_TAG_MANAGER_ID")
108
+ ```
109
+
110
+ If any of the configuration keys above are not set, your application will raise
111
+ an error during initialization. This method is preferred because it prevents
112
+ runtime errors in a production application due to improper configuration.
113
+
114
+ To require configuration keys lazily, reference the variables via "bang" methods
115
+ on `Figjam.env`:
116
+
117
+ ```ruby
118
+ gtm_id = Figjam.env.google_tag_manager_id!
119
+ ```
120
+
121
+ ## Is Figjam like [dotenv](https://github.com/bkeepers/dotenv)?
122
+
123
+ Figjam and dotenv are similar:
124
+
125
+ ### Similarities
126
+
127
+ * Both libraries are useful for Ruby application configuration.
128
+ * Both are inspired by Twelve-Factor App's concept of proper [configuration](http://12factor.net/config).
129
+ * Both store configuration values in `ENV`.
130
+ * Both can be used in and out of Rails.
131
+
132
+ ### Differences
133
+
134
+ * Configuration File
135
+ * Figjam expects a single file.
136
+ * Dotenv supports separate files for each environment.
137
+ * Configuration File Format
138
+ * Figjam expects YAML containing key/value pairs.
139
+ * Dotenv convention is a collection of `KEY=VALUE` pairs.
140
+
141
+ If you prefer your default configuration in one place, where you can scan one file to see
142
+ differences between environments, then you may prefer `figjam` over `dotenv`.
143
+
144
+ ## Is application.yml like [secrets.yml](https://github.com/rails/rails/blob/v4.1.0/railties/lib/rails/generators/rails/app/templates/config/secrets.yml)?
145
+
146
+ No. Do not put secrets in `figjam` `application.yml` files! That file supposed to be committed
147
+ to source control, and should never contain secrets.
148
+
149
+ ### Spring Configuration
150
+
151
+ If you're using Spring add `config/application.yml` to the watch list:
152
+
153
+ ```rb
154
+ # config/spring.rb
155
+
156
+ %w(
157
+ ...
158
+ config/application.yml
159
+ ).each { |path| Spring.watch(path) }
160
+ ```
161
+
162
+ ## Figjam origins
163
+
164
+ Figjam started as a direct fork of the [figaro](https://github.com/laserlemon/figaro) rubygem.
165
+
166
+ There are some key differences in philosophy:
167
+
168
+ 1. Figjam chooses not to go down the more "use ruby for configuration" 2.x path that gem was taking,
169
+ preferring to keep using hierarchical yaml files.
170
+ 2. Figjam prefers that you *do* commit your application.yml to your repository, as long as you don't
171
+ put any credentials or other secrets in it. It encourages an ENV-with-code-change PR flow
172
+ that simplifies providing default ENV values for an application, as well as codified
173
+ overrides per environment. These all, of course, can be overridden by a real ENV.
174
+
175
+ Given (2), it doesn't make sense to push ENV to Heroku from the application.yml file, so Heroku
176
+ support has been removed.
177
+
178
+ With those caveats, it can be used as a drop-in replacement for the `figaro` gem.
179
+ It even aliases the `Figaro` to `Figjam` module namespace for drop-in compatibility.
180
+
181
+ ## How can I help?
182
+
183
+ Figjam is open source and contributions from the community are encouraged! No
184
+ contribution is too small.
data/bin/figaro ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "figjam"
data/bin/figjam ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "figjam/cli"
4
+
5
+ Figjam::CLI.start
@@ -0,0 +1 @@
1
+ require "figjam/application"
@@ -0,0 +1 @@
1
+ require "figjam/rails"
data/lib/figaro.rb ADDED
@@ -0,0 +1 @@
1
+ require "figjam"
@@ -0,0 +1,91 @@
1
+ require "erb"
2
+ require "yaml"
3
+
4
+ module Figjam
5
+ class Application
6
+ FIGARO_ENV_PREFIX = "_FIGARO_"
7
+
8
+ include Enumerable
9
+
10
+ def initialize(options = {})
11
+ @options = options.inject({}) { |m, (k, v)| m[k.to_sym] = v; m }
12
+ end
13
+
14
+ def path
15
+ @options.fetch(:path) { default_path }.to_s
16
+ end
17
+
18
+ def path=(path)
19
+ @options[:path] = path
20
+ end
21
+
22
+ def environment
23
+ environment = @options.fetch(:environment) { default_environment }
24
+ environment.nil? ? nil : environment.to_s
25
+ end
26
+
27
+ def environment=(environment)
28
+ @options[:environment] = environment
29
+ end
30
+
31
+ def configuration
32
+ global_configuration.merge(environment_configuration)
33
+ end
34
+
35
+ def load
36
+ each do |key, value|
37
+ skip?(key) ? key_skipped!(key) : set(key, value)
38
+ end
39
+ end
40
+
41
+ def each(&block)
42
+ configuration.each(&block)
43
+ end
44
+
45
+ private
46
+
47
+ def default_path
48
+ raise NotImplementedError
49
+ end
50
+
51
+ def default_environment
52
+ nil
53
+ end
54
+
55
+ def raw_configuration
56
+ (@parsed ||= Hash.new { |hash, path| hash[path] = parse(path) })[path]
57
+ end
58
+
59
+ def parse(path)
60
+ File.exist?(path) && YAML.load(ERB.new(File.read(path)).result) || {}
61
+ end
62
+
63
+ def global_configuration
64
+ raw_configuration.reject { |_, value| value.is_a?(Hash) }
65
+ end
66
+
67
+ def environment_configuration
68
+ raw_configuration[environment] || {}
69
+ end
70
+
71
+ def set(key, value)
72
+ non_string_configuration!(key) unless key.is_a?(String)
73
+ non_string_configuration!(value) unless value.is_a?(String) || value.nil?
74
+
75
+ ::ENV[key.to_s] = value.nil? ? nil : value.to_s
76
+ ::ENV[FIGARO_ENV_PREFIX + key.to_s] = value.nil? ? nil: value.to_s
77
+ end
78
+
79
+ def skip?(key)
80
+ ::ENV.key?(key.to_s) && !::ENV.key?(FIGARO_ENV_PREFIX + key.to_s)
81
+ end
82
+
83
+ def non_string_configuration!(value)
84
+ warn "WARNING: Use strings for Figjam configuration. #{value.inspect} was converted to #{value.to_s.inspect}."
85
+ end
86
+
87
+ def key_skipped!(key)
88
+ warn "WARNING: Skipping key #{key.inspect}. Already set in ENV."
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,13 @@
1
+ # Add configuration values here, as shown below.
2
+ #
3
+ # GOOGLE_TAG_MANAGER_ID: GTM-12345
4
+ #
5
+ # test:
6
+ # # Use ~ for "nil"
7
+ # GOOGLE_TAG_MANAGER_ID: ~
8
+ #
9
+ # prelive:
10
+ # GOOGLE_TAG_MANAGER_ID: GTM-45678
11
+ #
12
+ # production:
13
+ # GOOGLE_TAG_MANAGER_ID: GTM-98765
@@ -0,0 +1,22 @@
1
+ require "thor/group"
2
+
3
+ module Figjam
4
+ class CLI < Thor
5
+ class Install < Thor::Group
6
+ include Thor::Actions
7
+
8
+ class_option "path",
9
+ aliases: ["-p"],
10
+ default: "config/application.yml",
11
+ desc: "Specify a configuration file path"
12
+
13
+ def self.source_root
14
+ File.expand_path("../install", __FILE__)
15
+ end
16
+
17
+ def create_configuration
18
+ copy_file("application.yml", options[:path])
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ require "figjam/application"
2
+
3
+ module Figjam
4
+ class CLI < Thor
5
+ class Task
6
+ attr_reader :options
7
+
8
+ def self.run(options = {})
9
+ new(options).run
10
+ end
11
+
12
+ def initialize(options = {})
13
+ @options = options
14
+ end
15
+
16
+ private
17
+
18
+ def env
19
+ ENV.to_hash.update(configuration)
20
+ end
21
+
22
+ def configuration
23
+ application.configuration
24
+ end
25
+
26
+ def application
27
+ @application ||= Figjam::Application.new(options)
28
+ end
29
+
30
+ if defined? Bundler
31
+ def system(*)
32
+ Bundler.with_clean_env { super }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/figjam/cli.rb ADDED
@@ -0,0 +1,19 @@
1
+ require "thor"
2
+
3
+ module Figjam
4
+ class CLI < Thor
5
+ # figjam install
6
+
7
+ desc "install", "Install Figjam"
8
+
9
+ method_option "path",
10
+ aliases: ["-p"],
11
+ default: "config/application.yml",
12
+ desc: "Specify a configuration file path"
13
+
14
+ def install
15
+ require "figjam/cli/install"
16
+ Install.start
17
+ end
18
+ end
19
+ end
data/lib/figjam/env.rb ADDED
@@ -0,0 +1,45 @@
1
+ module Figjam
2
+ module ENV
3
+ extend self
4
+
5
+ def respond_to?(method, *)
6
+ key, punctuation = extract_key_from_method(method)
7
+
8
+ case punctuation
9
+ when "!" then has_key?(key) || super
10
+ when "?", nil then true
11
+ else super
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def method_missing(method, *)
18
+ key, punctuation = extract_key_from_method(method)
19
+
20
+ case punctuation
21
+ when "!" then send(key) || missing_key!(key)
22
+ when "?" then !!send(key)
23
+ when nil then get_value(key)
24
+ else super
25
+ end
26
+ end
27
+
28
+ def extract_key_from_method(method)
29
+ method.to_s.downcase.match(/^(.+?)([!?=])?$/).captures
30
+ end
31
+
32
+ def has_key?(key)
33
+ ::ENV.any? { |k, _| k.downcase == key }
34
+ end
35
+
36
+ def missing_key!(key)
37
+ raise MissingKey.new(key)
38
+ end
39
+
40
+ def get_value(key)
41
+ _, value = ::ENV.detect { |k, _| k.downcase == key }
42
+ value
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ module Figjam
2
+ class Error < StandardError; end
3
+
4
+ class RailsNotInitialized < Error; end
5
+
6
+ class MissingKey < Error
7
+ def initialize(key)
8
+ super("Missing required configuration key: #{key.inspect}")
9
+ end
10
+ end
11
+
12
+ class MissingKeys < Error
13
+ def initialize(keys)
14
+ super("Missing required configuration keys: #{keys.inspect}")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Figjam
2
+ module Rails
3
+ class Application < Figjam::Application
4
+ private
5
+
6
+ def default_path
7
+ rails_not_initialized! unless ::Rails.root
8
+
9
+ ::Rails.root.join("config", "application.yml")
10
+ end
11
+
12
+ def default_environment
13
+ ::Rails.env
14
+ end
15
+
16
+ def rails_not_initialized!
17
+ raise RailsNotInitialized
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module Figjam
2
+ module Rails
3
+ class Railtie < ::Rails::Railtie
4
+ config.before_configuration do
5
+ Figjam.load
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ begin
2
+ require "rails"
3
+ rescue LoadError
4
+ else
5
+ require "figjam/rails/application"
6
+ require "figjam/rails/railtie"
7
+
8
+ Figjam.adapter = Figjam::Rails::Application
9
+ end
10
+
@@ -0,0 +1,6 @@
1
+ module Figjam
2
+ VERSION = "1.2.0"
3
+ end
4
+
5
+ # Alias for drop-in replacement support
6
+ Figaro = Figjam
data/lib/figjam.rb ADDED
@@ -0,0 +1,36 @@
1
+ if Gem.loaded_specs.key?("figaro")
2
+ raise "The gem figjam is a replacement for figaro. Remove figaro from your Gemfile."
3
+ end
4
+
5
+ require "figjam/error"
6
+ require "figjam/env"
7
+ require "figjam/application"
8
+
9
+ module Figjam
10
+ extend self
11
+
12
+ attr_writer :adapter, :application
13
+
14
+ def env
15
+ Figjam::ENV
16
+ end
17
+
18
+ def adapter
19
+ @adapter ||= Figjam::Application
20
+ end
21
+
22
+ def application
23
+ @application ||= adapter.new
24
+ end
25
+
26
+ def load
27
+ application.load
28
+ end
29
+
30
+ def require_keys(*keys)
31
+ missing_keys = keys.flatten - ::ENV.keys
32
+ raise MissingKeys.new(missing_keys) if missing_keys.any?
33
+ end
34
+ end
35
+
36
+ require "figjam/rails"
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: figjam
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Harry Lascelles
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-11-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 1.7.0
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '3'
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.7.0
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '3'
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 10.4.0
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '14'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 10.4.0
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '14'
73
+ description: ENV configuration for ruby using hierarchical environment yaml files
74
+ email:
75
+ - harry@harrylascelles.com
76
+ executables:
77
+ - figjam
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - README.md
82
+ - bin/figaro
83
+ - bin/figjam
84
+ - lib/figaro.rb
85
+ - lib/figaro/application.rb
86
+ - lib/figaro/rails.rb
87
+ - lib/figjam.rb
88
+ - lib/figjam/application.rb
89
+ - lib/figjam/cli.rb
90
+ - lib/figjam/cli/install.rb
91
+ - lib/figjam/cli/install/application.yml
92
+ - lib/figjam/cli/task.rb
93
+ - lib/figjam/env.rb
94
+ - lib/figjam/error.rb
95
+ - lib/figjam/rails.rb
96
+ - lib/figjam/rails/application.rb
97
+ - lib/figjam/rails/railtie.rb
98
+ - lib/figjam/version.rb
99
+ homepage: https://github.com/hlascelles/figjam
100
+ licenses:
101
+ - MIT
102
+ metadata:
103
+ homepage_uri: https://github.com/hlascelles/figjam
104
+ documentation_uri: https://github.com/hlascelles/figjam
105
+ changelog_uri: https://github.com/hlascelles/figjam/blob/master/CHANGELOG.md
106
+ source_code_uri: https://github.com/hlascelles/figjam/
107
+ bug_tracker_uri: https://github.com/hlascelles/figjam/issues
108
+ rubygems_mfa_required: 'true'
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubygems_version: 3.1.6
125
+ signing_key:
126
+ specification_version: 4
127
+ summary: ENV configuration for ruby using yaml files
128
+ test_files: []