runger_config 3.0.0 → 4.0.0
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 +4 -4
- data/CHANGELOG.md +45 -36
- data/README.md +83 -83
- data/lib/generators/{anyway → runger}/app_config/app_config_generator.rb +2 -2
- data/lib/generators/{anyway → runger}/config/config_generator.rb +3 -8
- data/lib/generators/{anyway → runger}/config/templates/config.rb.tt +0 -3
- data/lib/generators/{anyway → runger}/install/install_generator.rb +4 -4
- data/lib/generators/{anyway → runger}/install/templates/application_config.rb.tt +1 -1
- data/lib/{anyway → runger}/auto_cast.rb +1 -1
- data/lib/{anyway → runger}/config.rb +22 -22
- data/lib/{anyway → runger}/dynamic_config.rb +2 -2
- data/lib/{anyway → runger}/ejson_parser.rb +3 -3
- data/lib/{anyway → runger}/env.rb +3 -3
- data/lib/{anyway → runger}/ext/deep_dup.rb +1 -1
- data/lib/{anyway → runger}/ext/deep_freeze.rb +1 -1
- data/lib/{anyway → runger}/ext/flatten_names.rb +1 -1
- data/lib/{anyway → runger}/ext/hash.rb +1 -1
- data/lib/{anyway → runger}/ext/string_constantize.rb +1 -1
- data/lib/{anyway → runger}/loaders/base.rb +2 -2
- data/lib/{anyway → runger}/loaders/doppler.rb +2 -2
- data/lib/{anyway → runger}/loaders/ejson.rb +3 -3
- data/lib/{anyway → runger}/loaders/env.rb +2 -2
- data/lib/{anyway → runger}/loaders/yaml.rb +3 -3
- data/lib/{anyway → runger}/loaders.rb +6 -6
- data/lib/{anyway → runger}/option_parser_builder.rb +1 -1
- data/lib/{anyway → runger}/optparse_config.rb +6 -6
- data/lib/{anyway → runger}/rails/autoload.rb +5 -5
- data/lib/{anyway → runger}/rails/config.rb +3 -3
- data/lib/{anyway → runger}/rails/loaders/credentials.rb +2 -2
- data/lib/{anyway → runger}/rails/loaders/secrets.rb +3 -3
- data/lib/{anyway → runger}/rails/loaders/yaml.rb +2 -2
- data/lib/runger/rails/loaders.rb +5 -0
- data/lib/{anyway → runger}/rails/settings.rb +2 -2
- data/lib/runger/rails.rb +24 -0
- data/lib/{anyway → runger}/railtie.rb +7 -7
- data/lib/{anyway → runger}/rbs.rb +1 -1
- data/lib/{anyway → runger}/settings.rb +4 -4
- data/lib/{anyway → runger}/testing/helpers.rb +4 -4
- data/lib/{anyway → runger}/testing.rb +2 -2
- data/lib/{anyway → runger}/tracing.rb +4 -4
- data/lib/{anyway → runger}/type_casting.rb +4 -4
- data/lib/{anyway → runger}/utils/deep_merge.rb +2 -2
- data/lib/{anyway → runger}/utils/which.rb +1 -1
- data/lib/runger/version.rb +5 -0
- data/lib/{anyway.rb → runger.rb} +1 -1
- data/lib/runger_config.rb +49 -0
- data/sig/{anyway_config.rbs → runger_config.rbs} +1 -1
- metadata +51 -51
- data/lib/anyway/rails/loaders.rb +0 -5
- data/lib/anyway/rails.rb +0 -24
- data/lib/anyway/version.rb +0 -5
- data/lib/anyway_config.rb +0 -49
- /data/lib/generators/{anyway → runger}/app_config/USAGE +0 -0
- /data/lib/generators/{anyway → runger}/config/USAGE +0 -0
- /data/lib/generators/{anyway → runger}/config/templates/config.yml.tt +0 -0
- /data/lib/generators/{anyway → runger}/install/USAGE +0 -0
data/README.md
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
[](https://cultofmartians.com/tasks/
|
1
|
+
[](https://cultofmartians.com/tasks/runger-config-options-parse.html#task)
|
2
2
|
[](https://rubygems.org/gems/runger_config) [](https://github.com/davidrunger/runger_config/actions)
|
3
3
|
[](https://github.com/davidrunger/runger_config/actions)
|
4
4
|
[](https://github.com/davidrunger/runger_config/actions)
|
5
5
|
|
6
|
-
#
|
6
|
+
# Runger Config
|
7
7
|
|
8
8
|
> One configuration to rule all data sources
|
9
9
|
|
10
|
-
|
10
|
+
Runger Config is a configuration library for Ruby gems and applications.
|
11
11
|
|
12
|
-
As a library author, you can benefit from using
|
12
|
+
As a library author, you can benefit from using Runger Config by providing a better UX for your end-users:
|
13
13
|
|
14
14
|
- **Zero-code configuration** — no more boilerplate initializers.
|
15
15
|
- **Per-environment and local** settings support out-of-the-box.
|
16
16
|
|
17
|
-
For application developers,
|
17
|
+
For application developers, Runger Config could be useful to:
|
18
18
|
|
19
19
|
- **Keep configuration organized** and use _named configs_ instead of bloated `.env`/`settings.yml`/whatever.
|
20
20
|
- **Free code of ENV/credentials/secrets dependency** and use configuration classes instead—your code should not rely on configuration data sources.
|
@@ -27,7 +27,7 @@ For version 1.x see the [1-4-stable branch](https://github.com/davidrunger/runge
|
|
27
27
|
|
28
28
|
## Links
|
29
29
|
|
30
|
-
- [
|
30
|
+
- [Runger Config: Keep your Ruby configuration sane](https://evilmartians.com/chronicles/runger-config-keep-your-ruby-configuration-sane?utm_source=runger_config)
|
31
31
|
|
32
32
|
## Table of contents
|
33
33
|
|
@@ -57,11 +57,11 @@ For version 1.x see the [1-4-stable branch](https://github.com/davidrunger/runge
|
|
57
57
|
|
58
58
|
## Main concepts
|
59
59
|
|
60
|
-
|
60
|
+
Runger Config abstractize the configuration layer by introducing **configuration classes** which describe available parameters and their defaults. For [example](https://github.com/palkan/influxer/blob/master/lib/influxer/config.rb):
|
61
61
|
|
62
62
|
```ruby
|
63
63
|
module Influxer
|
64
|
-
class Config <
|
64
|
+
class Config < Runger::Config
|
65
65
|
attr_config(
|
66
66
|
host: "localhost",
|
67
67
|
username: "root",
|
@@ -75,7 +75,7 @@ Using Ruby classes to represent configuration allows you to add helper methods a
|
|
75
75
|
|
76
76
|
The `runger_config` gem takes care of loading parameters from **different sources** (YAML, credentials/secrets, environment variables, etc.). Internally, we use a _pipeline pattern_ and provide the [Loaders API](#data-loaders) to manage and [extend](#custom-loaders) its functionality.
|
77
77
|
|
78
|
-
Check out the libraries using
|
78
|
+
Check out the libraries using Runger Config for more examples:
|
79
79
|
|
80
80
|
- [Influxer](https://github.com/palkan/influxer)
|
81
81
|
- [AnyCable](https://github.com/anycable/anycable)
|
@@ -115,13 +115,13 @@ gem "runger_config", "~> 2.0"
|
|
115
115
|
Using configuration classes allows you to make configuration data a bit more than a bag of values:
|
116
116
|
you can define a schema for your configuration, provide defaults, add validations and additional helper methods.
|
117
117
|
|
118
|
-
|
118
|
+
Runger Config provides a base class to inherit from with a few DSL methods:
|
119
119
|
|
120
120
|
```ruby
|
121
121
|
require "runger_config"
|
122
122
|
|
123
123
|
module MyCoolGem
|
124
|
-
class Config <
|
124
|
+
class Config < Runger::Config
|
125
125
|
attr_config user: "root", password: "root", host: "localhost"
|
126
126
|
end
|
127
127
|
end
|
@@ -141,7 +141,7 @@ Then, create an instance of the config class and use it:
|
|
141
141
|
MyCoolGem::Config.new.user #=> "root"
|
142
142
|
```
|
143
143
|
|
144
|
-
**Bonus:**: if you define attributes with boolean default values (`false` or `true`),
|
144
|
+
**Bonus:**: if you define attributes with boolean default values (`false` or `true`), Runger Config would automatically add a corresponding predicate method. For example:
|
145
145
|
|
146
146
|
```ruby
|
147
147
|
attr_config :user, :password, debug: false
|
@@ -153,7 +153,7 @@ MyCoolGem::Config.new(debug: true).debug? #=> true
|
|
153
153
|
**NOTE**: since v2.0 accessors created by `attr_config` are not `attr_accessor`, i.e. they do not populate instance variables. If you used instance variables before to override readers, you must switch to using `super` or `values` store:
|
154
154
|
|
155
155
|
```ruby
|
156
|
-
class MyConfig <
|
156
|
+
class MyConfig < Runger::Config
|
157
157
|
attr_config :host, :port, :url, :meta
|
158
158
|
|
159
159
|
# override writer to handle type coercion
|
@@ -191,9 +191,9 @@ end
|
|
191
191
|
|
192
192
|
#### Config name
|
193
193
|
|
194
|
-
|
194
|
+
Runger Config relies on the notion of _config name_ to populate data.
|
195
195
|
|
196
|
-
By default,
|
196
|
+
By default, Runger Config uses the config class name to infer the config name using the following rules:
|
197
197
|
|
198
198
|
- if the class name has a form of `<Module>::Config` then use the module name (`SomeModule::Config => "somemodule"`)
|
199
199
|
- if the class name has a form of `<Something>Config` then use the class name prefix (`SomeConfig => "some"`)
|
@@ -204,7 +204,7 @@ You can also specify the config name explicitly (it's required in cases when you
|
|
204
204
|
|
205
205
|
```ruby
|
206
206
|
module MyCoolGem
|
207
|
-
class Config <
|
207
|
+
class Config < Runger::Config
|
208
208
|
config_name :cool
|
209
209
|
attr_config user: "root", password: "root", host: "localhost", options: {}
|
210
210
|
end
|
@@ -213,14 +213,14 @@ end
|
|
213
213
|
|
214
214
|
#### Customize env variable names prefix
|
215
215
|
|
216
|
-
By default,
|
216
|
+
By default, Runger Config uses upper-cased config name as a prefix for env variable names (e.g.
|
217
217
|
`config_name :my_app` will result to parsing `MY_APP_` prefix).
|
218
218
|
|
219
219
|
You can set env prefix explicitly:
|
220
220
|
|
221
221
|
```ruby
|
222
222
|
module MyCoolGem
|
223
|
-
class Config <
|
223
|
+
class Config < Runger::Config
|
224
224
|
config_name :cool_gem
|
225
225
|
env_prefix :really_cool # now variables, starting wih `REALLY_COOL_`, will be parsed
|
226
226
|
attr_config user: "root", password: "root", host: "localhost", options: {}
|
@@ -258,16 +258,16 @@ You can also fetch configuration without pre-defined schema:
|
|
258
258
|
# credentials.my_app, secrets.my_app (if using Rails), ENV["MY_APP_*"]
|
259
259
|
#
|
260
260
|
# Given MY_APP_VALUE=42
|
261
|
-
config =
|
261
|
+
config = Runger::Config.for(:my_app)
|
262
262
|
config["value"] #=> 42
|
263
263
|
|
264
264
|
# you can specify the config file path or env prefix
|
265
|
-
config =
|
265
|
+
config = Runger::Config.for(:my_app, config_path: "my_config.yml", env_prefix: "MYAPP")
|
266
266
|
```
|
267
267
|
|
268
268
|
This feature is similar to `Rails.application.config_for` but more powerful:
|
269
269
|
|
270
|
-
| Feature | Rails |
|
270
|
+
| Feature | Rails | Runger Config |
|
271
271
|
| ------------- |-------------:| -----:|
|
272
272
|
| Load data from `config/app.yml` | ✅ | ✅ |
|
273
273
|
| Load data from `secrets` | ❌ | ✅ |
|
@@ -286,26 +286,26 @@ This feature is similar to `Rails.application.config_for` but more powerful:
|
|
286
286
|
|
287
287
|
### Validation and callbacks
|
288
288
|
|
289
|
-
|
289
|
+
Runger Config provides basic ways of ensuring that the configuration is valid.
|
290
290
|
|
291
291
|
There is a built-in `required` class method to define the list of parameters that must be present in the
|
292
292
|
configuration after loading (where present means non-`nil` and non-empty for strings):
|
293
293
|
|
294
294
|
```ruby
|
295
|
-
class MyConfig <
|
295
|
+
class MyConfig < Runger::Config
|
296
296
|
attr_config :api_key, :api_secret, :debug
|
297
297
|
|
298
298
|
required :api_key, :api_secret
|
299
299
|
end
|
300
300
|
|
301
|
-
MyConfig.new(api_secret: "") #=> raises
|
301
|
+
MyConfig.new(api_secret: "") #=> raises Runger::Config::ValidationError
|
302
302
|
```
|
303
303
|
|
304
304
|
`Required` method supports additional `env` parameter which indicates necessity to run validations under specified
|
305
305
|
environments. `Env` parameter could be present in symbol, string, array or hash formats:
|
306
306
|
|
307
307
|
```ruby
|
308
|
-
class EnvConfig <
|
308
|
+
class EnvConfig < Runger::Config
|
309
309
|
required :password, env: "production"
|
310
310
|
required :maps_api_key, env: :production
|
311
311
|
required :smtp_host, env: %i[production staging]
|
@@ -316,13 +316,13 @@ class EnvConfig < Anyway::Config
|
|
316
316
|
end
|
317
317
|
```
|
318
318
|
|
319
|
-
If your current `
|
320
|
-
`
|
319
|
+
If your current `Runger::Settings.current_environment` is mismatch keys that specified
|
320
|
+
`Runger::Config::ValidationError` error will be raised.
|
321
321
|
|
322
322
|
If you need more complex validation or need to manipulate with config state right after it has been loaded, you can use _on load callbacks_ and `#raise_validation_error` method:
|
323
323
|
|
324
324
|
```ruby
|
325
|
-
class MyConfig <
|
325
|
+
class MyConfig < Runger::Config
|
326
326
|
attr_config :api_key, :api_secret, :mode
|
327
327
|
|
328
328
|
# on_load macro accepts symbol method names
|
@@ -348,7 +348,7 @@ end
|
|
348
348
|
**NOTE:** version 2.x supports Rails >= 5.0; for Rails 4.x use version 1.x of the gem.
|
349
349
|
|
350
350
|
We recommend going through [Data population](#data-population) and [Organizing configs](#organizing-configs) sections first,
|
351
|
-
and then use [Rails generators](#generators) to make your application
|
351
|
+
and then use [Rails generators](#generators) to make your application Runger Config-ready.
|
352
352
|
|
353
353
|
### Data population
|
354
354
|
|
@@ -368,7 +368,7 @@ development:
|
|
368
368
|
port: 3000
|
369
369
|
```
|
370
370
|
|
371
|
-
**NOTE:** You can override the environment name for configuration files via the `
|
371
|
+
**NOTE:** You can override the environment name for configuration files via the `RUNGER_ENV` environment variable or by setting it explicitly in the code: `Runger::Settings.current_environment = "some_other_env"`.
|
372
372
|
|
373
373
|
### Multi-env configuration
|
374
374
|
|
@@ -397,13 +397,13 @@ staging:
|
|
397
397
|
port: 3002 # This value will not be loaded at all
|
398
398
|
```
|
399
399
|
|
400
|
-
To provide default values you can use YAML anchors, but they do not deep-merge settings, so
|
400
|
+
To provide default values you can use YAML anchors, but they do not deep-merge settings, so Runger Config provides a way to define a special top-level key for default values like this:
|
401
401
|
|
402
402
|
```ruby
|
403
403
|
config.runger_config.default_environmental_key = "default"
|
404
404
|
```
|
405
405
|
|
406
|
-
After that,
|
406
|
+
After that, Runger Config will start reading settings under the `"default"` key and then merge environmental settings into them.
|
407
407
|
|
408
408
|
```yml
|
409
409
|
default:
|
@@ -443,7 +443,7 @@ development:
|
|
443
443
|
port: 4444
|
444
444
|
```
|
445
445
|
|
446
|
-
**NOTE:** If you want to use secrets with Rails 7.1 (still supported, but deprecated) you must add the corresponding loader manually: `
|
446
|
+
**NOTE:** If you want to use secrets with Rails 7.1 (still supported, but deprecated) you must add the corresponding loader manually: `Runger.loaders.insert_after :yml, :secrets, Runger::Rails::Loaders::Secrets`.
|
447
447
|
|
448
448
|
3) **Rails credentials**: `Rails.application.credentials.my_cool_gem` (if supported):
|
449
449
|
|
@@ -473,7 +473,7 @@ We have the following config to fetch the Heroku provided [metadata](https://dev
|
|
473
473
|
|
474
474
|
```ruby
|
475
475
|
# This data is provided by Heroku Dyno Metadadata add-on.
|
476
|
-
class HerokuConfig <
|
476
|
+
class HerokuConfig < Runger::Config
|
477
477
|
attr_config :app_id, :app_name,
|
478
478
|
:dyno_id, :release_version,
|
479
479
|
:slug_commit
|
@@ -518,28 +518,28 @@ end
|
|
518
518
|
|
519
519
|
### Generators
|
520
520
|
|
521
|
-
|
521
|
+
Runger Config provides Rails generators to create new config classes:
|
522
522
|
|
523
|
-
- `rails g
|
523
|
+
- `rails g runger:install`—creates an `ApplicationConfig` class (the base class for all config classes) and updates `.gitignore`
|
524
524
|
|
525
525
|
You can specify the static configs path via the `--configs-path` option:
|
526
526
|
|
527
527
|
```sh
|
528
|
-
rails g
|
528
|
+
rails g runger:install --configs-path=config/settings
|
529
529
|
|
530
530
|
# or to keep everything in app/configs
|
531
|
-
rails g
|
531
|
+
rails g runger:install --configs-path=app/configs
|
532
532
|
```
|
533
533
|
|
534
|
-
- `rails g
|
534
|
+
- `rails g runger:config <name> param1 param2 ...`—creates a named configuration class and optionally the corresponding YAML file; creates `application_config.rb` is missing.
|
535
535
|
|
536
536
|
The generator command for the Heroku example above would be:
|
537
537
|
|
538
538
|
```sh
|
539
|
-
$ rails g
|
539
|
+
$ rails g runger:config heroku app_id app_name dyno_id release_version slug_commit
|
540
540
|
|
541
|
-
generate
|
542
|
-
rails generate
|
541
|
+
generate runger:install
|
542
|
+
rails generate runger:install
|
543
543
|
create config/configs/application_config.rb
|
544
544
|
append .gitignore
|
545
545
|
create config/configs/heroku_config.rb
|
@@ -547,17 +547,17 @@ Would you like to generate a heroku.yml file? (Y/n) n
|
|
547
547
|
```
|
548
548
|
|
549
549
|
You can also specify the `--app` option to put the newly created class into `app/configs` folder.
|
550
|
-
Alternatively, you can call `rails g
|
550
|
+
Alternatively, you can call `rails g runger:app_config name param1 param2 ...`.
|
551
551
|
|
552
|
-
**NOTE:** The generated `ApplicationConfig` class uses a singleton pattern along with `delegate_missing_to` to re-use the same instance across the application. However, the delegation can lead to unexpected behaviour and break
|
552
|
+
**NOTE:** The generated `ApplicationConfig` class uses a singleton pattern along with `delegate_missing_to` to re-use the same instance across the application. However, the delegation can lead to unexpected behaviour and break Runger Config internals if you have attributes named as `Runger::Config` class methods. See [#120](https://github.com/davidrunger/runger_config/issues/120).
|
553
553
|
|
554
|
-
### Loading
|
554
|
+
### Loading Runger Config before Rails
|
555
555
|
|
556
|
-
|
556
|
+
Runger Config activates Rails-specific features automatically on the gem load only if Rails has been already required (we check for the `Rails::VERSION` constant presence). However, in some cases you may want to use Runger Config before Rails initialization (e.g., in `config/puma.rb` when starting a Puma web server).
|
557
557
|
|
558
|
-
By default,
|
558
|
+
By default, Runger Config sets up a hook (via TracePoint API) and waits for Rails to be loaded to require the Rails extensions (`require "runger/rails"`). In case you load Rails after Runger Config, you will see a warning telling you about that. Note that config classes loaded before Rails are not populated from Rails-specific data sources (e.g., credentials).
|
559
559
|
|
560
|
-
You can disable the warning by setting `
|
560
|
+
You can disable the warning by setting `Runger::Rails.disable_postponed_load_warning = true` in your application. Also, you can disable the _hook_ completely by calling `Runger::Rails.tracer.disable`.
|
561
561
|
|
562
562
|
## Using with Ruby
|
563
563
|
|
@@ -566,13 +566,13 @@ The default data loading mechanism for non-Rails applications is the following (
|
|
566
566
|
1) **YAML configuration files**: `./config/<config-name>.yml`.
|
567
567
|
|
568
568
|
In pure Ruby apps, we also can load data under specific _environments_ (`test`, `development`, `production`, etc.).
|
569
|
-
If you want to enable this feature you must specify `
|
569
|
+
If you want to enable this feature you must specify `Runger::Settings.current_environment` variable for load config under specific environment.
|
570
570
|
|
571
571
|
```ruby
|
572
|
-
|
572
|
+
Runger::Settings.current_environment = "development"
|
573
573
|
```
|
574
574
|
|
575
|
-
You can also specify the `
|
575
|
+
You can also specify the `RUNGER_ENV=development` environment variable to set the current environment for configuration.
|
576
576
|
|
577
577
|
YAML files should be in this format:
|
578
578
|
|
@@ -582,7 +582,7 @@ development:
|
|
582
582
|
port: 3000
|
583
583
|
```
|
584
584
|
|
585
|
-
If `
|
585
|
+
If `Runger::Settings.current_environment` is missed we assume that the YAML contains values for a single environment:
|
586
586
|
|
587
587
|
```yml
|
588
588
|
host: localhost
|
@@ -593,16 +593,16 @@ port: 3000
|
|
593
593
|
|
594
594
|
You can specify the lookup path for YAML files in one of the following ways:
|
595
595
|
|
596
|
-
- By setting `
|
596
|
+
- By setting `Runger::Settings.default_config_path` to a target directory path:
|
597
597
|
|
598
598
|
```ruby
|
599
|
-
|
599
|
+
Runger::Settings.default_config_path = "/etc/configs"
|
600
600
|
```
|
601
601
|
|
602
|
-
- By setting `
|
602
|
+
- By setting `Runger::Settings.default_config_path` to a Proc, which accepts a config name and returns the path:
|
603
603
|
|
604
604
|
```ruby
|
605
|
-
|
605
|
+
Runger::Settings.default_config_path = ->(name) { Rails.root.join("data", "configs", "#{name}.yml") }
|
606
606
|
```
|
607
607
|
|
608
608
|
- By overriding a specific config YML file path via the `<NAME>_CONF` env variable, e.g., `MYCOOLGEM_CONF=path/to/cool.yml`
|
@@ -626,7 +626,7 @@ By default, environment variables are automatically type cast (rules are case-in
|
|
626
626
|
|
627
627
|
Type coercion can be [customized or disabled](#type-coercion).
|
628
628
|
|
629
|
-
*
|
629
|
+
*Runger Config* supports nested (_hashed_) env variables—just separate keys with double-underscore.
|
630
630
|
|
631
631
|
For example, "MYCOOLGEM_OPTIONS__VERBOSE" is parsed as `config.options["verbose"]`.
|
632
632
|
|
@@ -650,7 +650,7 @@ MYCOOLGEM = "Nif-Nif, Naf-Naf and Nouf-Nouf"
|
|
650
650
|
You can define custom type coercion rules to convert string data to config values. To do that, use `.coerce_types` method:
|
651
651
|
|
652
652
|
```ruby
|
653
|
-
class CoolConfig <
|
653
|
+
class CoolConfig < Runger::Config
|
654
654
|
config_name :cool
|
655
655
|
attr_config port: 8080,
|
656
656
|
host: "localhost",
|
@@ -691,7 +691,7 @@ coerce_types non_list: :string
|
|
691
691
|
Finally, it's possible to disable auto-casting for a particular config completely:
|
692
692
|
|
693
693
|
```ruby
|
694
|
-
class CoolConfig <
|
694
|
+
class CoolConfig < Runger::Config
|
695
695
|
attr_config port: 8080,
|
696
696
|
host: "localhost",
|
697
697
|
user: {name: "admin", password: "admin"}
|
@@ -722,7 +722,7 @@ COLOR_TO_HEX = lambda do |raw|
|
|
722
722
|
end
|
723
723
|
end
|
724
724
|
|
725
|
-
class CoolConfig <
|
725
|
+
class CoolConfig < Runger::Config
|
726
726
|
attr_config :color
|
727
727
|
|
728
728
|
coerce_types color: COLOR_TO_HEX
|
@@ -743,7 +743,7 @@ We support this by looking at _local_ files when loading the configuration data:
|
|
743
743
|
\* If the YAML config path is not a default one (i.e., set via `<CONFIG_NAME>_CONF`), we look up the local
|
744
744
|
config at this location, too.
|
745
745
|
|
746
|
-
Local configs are meant for using in development and only loaded if `
|
746
|
+
Local configs are meant for using in development and only loaded if `Runger::Settings.use_local_files` is `true` (which is true by default if `RACK_ENV` or `RAILS_ENV` env variable is equal to `"development"`).
|
747
747
|
|
748
748
|
**NOTE:** in Rails apps you can use `Rails.application.configuration.runger_config.use_local_files`.
|
749
749
|
|
@@ -755,24 +755,24 @@ Don't forget to add `*.local.yml` (and `config/credentials/local.*`) to your `.g
|
|
755
755
|
|
756
756
|
### Doppler integration
|
757
757
|
|
758
|
-
|
758
|
+
Runger Config can pull configuration data from [Doppler](https://www.doppler.com/). All you need is to specify the `DOPPLER_TOKEN` environment variable with the **service token**, associated with the specific content (read more about [service tokens](https://docs.doppler.com/docs/service-tokens)).
|
759
759
|
|
760
760
|
You can also configure Doppler loader manually if needed:
|
761
761
|
|
762
762
|
```ruby
|
763
763
|
# Add loader
|
764
|
-
|
764
|
+
Runger.loaders.append :Doppler, Runger::Loaders::Doppler
|
765
765
|
|
766
766
|
# Configure API URL and token (defaults are shown)
|
767
|
-
|
768
|
-
|
767
|
+
Runger::Loaders::Doppler.download_url = "https://api.doppler.com/v3/configs/config/secrets/download"
|
768
|
+
Runger::Loaders::Doppler.token = ENV["DOPPLER_TOKEN"]
|
769
769
|
```
|
770
770
|
|
771
|
-
**NOTE:** You can opt-out from Doppler loader by specifying the`
|
771
|
+
**NOTE:** You can opt-out from Doppler loader by specifying the`RUNGER_CONFIG_DISABLE_DOPPLER=true` env var (in case you have the `DOPPLER_TOKEN` env var, but don't want to use it with Runger Config).
|
772
772
|
|
773
773
|
### EJSON support
|
774
774
|
|
775
|
-
|
775
|
+
Runger Config allows you to keep your configuration also in encrypted `.ejson` files. More information
|
776
776
|
about EJSON format you can read [here](https://github.com/Shopify/ejson).
|
777
777
|
|
778
778
|
Configuration will be loaded only if you have `ejson` executable in your PATH. Easiest way to do this - install `ejson` as a gem into project:
|
@@ -810,7 +810,7 @@ ejson decrypt config/secrets.ejson
|
|
810
810
|
You can customize the JSON namespace under which a loader searches for configuration via `loader_options`:
|
811
811
|
|
812
812
|
```ruby
|
813
|
-
class MyConfig <
|
813
|
+
class MyConfig < Runger::Config
|
814
814
|
# To look under the key "foo" instead of the default key of "my"
|
815
815
|
loader_options ejson_namespace: "foo"
|
816
816
|
|
@@ -825,10 +825,10 @@ You can provide your own data loaders or change the existing ones using the Load
|
|
825
825
|
|
826
826
|
```ruby
|
827
827
|
# remove env loader => do not load params from ENV
|
828
|
-
|
828
|
+
Runger.loaders.delete :env
|
829
829
|
|
830
830
|
# add custom loader before :env (it's better to keep the ENV loader the last one)
|
831
|
-
|
831
|
+
Runger.loaders.insert_before :env, :my_loader, MyLoader
|
832
832
|
```
|
833
833
|
|
834
834
|
Loader is a _callable_ Ruby object (module/class responding to `.call` or lambda/proc), which `call` method
|
@@ -840,13 +840,13 @@ def call(
|
|
840
840
|
env_prefix:, # prefix for env vars if any
|
841
841
|
config_path:, # path to YML config
|
842
842
|
local:, # true|false, whether to load local configuration
|
843
|
-
**options # custom options can be passed via
|
843
|
+
**options # custom options can be passed via Runger::Config.loader_options example: "custom", option: "blah"
|
844
844
|
)
|
845
845
|
#=> must return Hash with configuration data
|
846
846
|
end
|
847
847
|
```
|
848
848
|
|
849
|
-
You can use `
|
849
|
+
You can use `Runger::Loaders::Base` as a base class for your loader and define a `#call` method.
|
850
850
|
For example, the [Chamber](https://github.com/thekompanee/chamber) loader could be written as follows:
|
851
851
|
|
852
852
|
```ruby
|
@@ -860,7 +860,7 @@ class ChamberConfigLoader < Base
|
|
860
860
|
end
|
861
861
|
|
862
862
|
# Don't forget to register it
|
863
|
-
|
863
|
+
Runger.loaders.insert_before :env, :chamber, ChamberConfigLoader
|
864
864
|
```
|
865
865
|
|
866
866
|
In order to support [source tracing](#tracing), you need to wrap the resulting Hash via the `#trace!` method with metadata:
|
@@ -878,9 +878,9 @@ end
|
|
878
878
|
|
879
879
|
## Tracing
|
880
880
|
|
881
|
-
Since
|
881
|
+
Since Runger Config loads data from multiple source, it could be useful to know where a particular value came from.
|
882
882
|
|
883
|
-
Each `
|
883
|
+
Each `Runger::Config` instance contains _tracing information_ which you can access via `#to_source_trace` method:
|
884
884
|
|
885
885
|
```ruby
|
886
886
|
conf = ExampleConfig.new
|
@@ -899,12 +899,12 @@ conf.to_source_trace
|
|
899
899
|
# if you change the value manually in your code,
|
900
900
|
# that would be reflected in the trace
|
901
901
|
|
902
|
-
conf.host = "
|
902
|
+
conf.host = "runger.host"
|
903
903
|
conf.to_source_trace["host"]
|
904
904
|
#=> {type: :user, called_from: "/path/to/caller.rb:15"}
|
905
905
|
```
|
906
906
|
|
907
|
-
You can disable tracing functionality by setting `
|
907
|
+
You can disable tracing functionality by setting `Runger::Settings.tracing_enabled = false` or `config.runger_config.tracing_enabled = false` in Rails.
|
908
908
|
|
909
909
|
### Pretty print
|
910
910
|
|
@@ -986,7 +986,7 @@ If you want to delete the env var, pass `nil` as the value.
|
|
986
986
|
|
987
987
|
This helper is automatically included to RSpec if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". It's only available for the example with the tag `type: :config` or with the path `spec/configs/...`.
|
988
988
|
|
989
|
-
You can add it manually by requiring `"
|
989
|
+
You can add it manually by requiring `"runger/testing/helpers"` and including the `Runger::Testing::Helpers` module (into RSpec configuration or Minitest test class).
|
990
990
|
|
991
991
|
## OptionParser integration
|
992
992
|
|
@@ -996,7 +996,7 @@ It's possible to use config as option parser (e.g., for CLI apps/libraries). It
|
|
996
996
|
Example usage:
|
997
997
|
|
998
998
|
```ruby
|
999
|
-
class MyConfig <
|
999
|
+
class MyConfig < Runger::Config
|
1000
1000
|
attr_config :host, :log_level, :concurrency, :debug, server_args: {}
|
1001
1001
|
|
1002
1002
|
# specify which options shouldn't be handled by option parser
|
@@ -1052,7 +1052,7 @@ describe_options(
|
|
1052
1052
|
|
1053
1053
|
## RBS support
|
1054
1054
|
|
1055
|
-
|
1055
|
+
Runger Config comes with Ruby type signatures (RBS).
|
1056
1056
|
|
1057
1057
|
To use them with Steep, add the following your `Steepfile`:
|
1058
1058
|
|
@@ -1065,7 +1065,7 @@ library "runger_config"
|
|
1065
1065
|
We also provide an API to generate a type signature for your config class:
|
1066
1066
|
|
1067
1067
|
```ruby
|
1068
|
-
class MyGem::Config <
|
1068
|
+
class MyGem::Config < Runger::Config
|
1069
1069
|
attr_config :host, port: 8080, tags: [], debug: false
|
1070
1070
|
|
1071
1071
|
coerce_types host: :string, port: :integer,
|
@@ -1091,7 +1091,7 @@ module MyGem
|
|
1091
1091
|
def debug=: (bool) -> void
|
1092
1092
|
end
|
1093
1093
|
|
1094
|
-
class Config <
|
1094
|
+
class Config < Runger::Config
|
1095
1095
|
include _Config
|
1096
1096
|
end
|
1097
1097
|
end
|
@@ -1102,7 +1102,7 @@ end
|
|
1102
1102
|
When we use `on_load` callback with a block, we switch the context (via `instance_eval`), and we need to provide type hints for the type checker. Here is an example:
|
1103
1103
|
|
1104
1104
|
```ruby
|
1105
|
-
class MyConfig <
|
1105
|
+
class MyConfig < Runger::Config
|
1106
1106
|
on_load do
|
1107
1107
|
# @type self : MyConfig
|
1108
1108
|
raise_validation_error("host is invalid") if host.start_with?("localhost")
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "generators/
|
3
|
+
require "generators/runger/config/config_generator"
|
4
4
|
|
5
|
-
module
|
5
|
+
module Runger
|
6
6
|
module Generators
|
7
7
|
class AppConfigGenerator < ConfigGenerator
|
8
8
|
source_root ConfigGenerator.source_root
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
|
5
|
-
module
|
5
|
+
module Runger
|
6
6
|
module Generators
|
7
7
|
class ConfigGenerator < ::Rails::Generators::NamedBase
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
@@ -15,7 +15,7 @@ module Anyway
|
|
15
15
|
|
16
16
|
def run_install_if_needed
|
17
17
|
return if ::Rails.root.join(static_config_root, "application_config.rb").exist?
|
18
|
-
generate "
|
18
|
+
generate "runger:install"
|
19
19
|
end
|
20
20
|
|
21
21
|
def create_config
|
@@ -31,7 +31,7 @@ module Anyway
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def static_config_root
|
34
|
-
|
34
|
+
Runger::Settings.autoload_static_config_path || Runger::DEFAULT_CONFIGS_PATH
|
35
35
|
end
|
36
36
|
|
37
37
|
def config_root
|
@@ -41,11 +41,6 @@ module Anyway
|
|
41
41
|
static_config_root
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
45
|
-
def needs_config_name?
|
46
|
-
raise "No longer needed" if Gem::Version.new(Anyway::VERSION) >= Gem::Version.new("3.0.0")
|
47
|
-
file_name.include?("_")
|
48
|
-
end
|
49
44
|
end
|
50
45
|
end
|
51
46
|
end
|
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
<% module_namespacing do -%>
|
4
4
|
class <%= class_name %>Config < ApplicationConfig
|
5
|
-
<%- if needs_config_name? %>
|
6
|
-
config_name :<%= file_name %>
|
7
|
-
<%- end -%>
|
8
5
|
<%- unless parameters.empty? -%>
|
9
6
|
attr_config <%= parameters.map { |param| ":#{param}" }.join(", ") %>
|
10
7
|
<%- end -%>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
|
5
|
-
module
|
5
|
+
module Runger
|
6
6
|
module Generators
|
7
7
|
class InstallGenerator < ::Rails::Generators::Base
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
@@ -26,7 +26,7 @@ module Anyway
|
|
26
26
|
<<-RUBY
|
27
27
|
# Configure the path for configuration classes that should be used before initialization
|
28
28
|
# NOTE: path should be relative to the project root (Rails.root)
|
29
|
-
#{maybe_comment_indented}config.
|
29
|
+
#{maybe_comment_indented}config.runger_config.autoload_static_config_path = "#{static_config_root}"
|
30
30
|
#{maybe_comment_indented.sub(/\s+$/, "")}
|
31
31
|
RUBY
|
32
32
|
end
|
@@ -36,11 +36,11 @@ module Anyway
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def static_config_root
|
39
|
-
options[:configs_path] ||
|
39
|
+
options[:configs_path] || Runger::Settings.autoload_static_config_path || Runger::DEFAULT_CONFIGS_PATH
|
40
40
|
end
|
41
41
|
|
42
42
|
def default_configs_path?
|
43
|
-
static_config_root == (
|
43
|
+
static_config_root == (Runger::Settings.autoload_static_config_path || Runger::DEFAULT_CONFIGS_PATH)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Base class for application config classes
|
4
|
-
class ApplicationConfig <
|
4
|
+
class ApplicationConfig < Runger::Config
|
5
5
|
class << self
|
6
6
|
# Make it possible to access a singleton config instance
|
7
7
|
# via class methods (i.e., without explicitly calling `instance`)
|