palkan / anyway_config

Configuration library for Ruby gems and applications
MIT License
778 stars 52 forks source link

Multiple sources of config files #78

Closed airtonix closed 3 years ago

airtonix commented 3 years ago

Is your feature request related to a problem? Please describe.

We're using Fastlane, but my background is NodeJs and Python. I'm a complete Ruby noob.

In the nodejs world we have the awesome nconf tool to allow us to do something very similar to what anway_config does, except with one important difference, I can easily control the load order and I can easily specify as many file sources as I like.

An example of how I would solve this in Nodejs is

this'd be in a npm module whose module name was '@us/config'

# values found in sources win based on when the source is defined. earlier sources win over later sources.

const nconf = require("nconf");
const REPO_ROOT = "a path to the root of the repo"

module.exports = function options({
  extra_file_sources = []
}) {

# argv source
nconf.argv()

# envvar source
nconf.env({
  separator: "__",
  whitelist: /^MY_ENVVAR_PREFIX_/
})

# file source
nconf.file(`${REPO_ROOT}/config.json`);

extra_file_sources.forEach(source => nconf.file(`${source}/config.json`); )

# returns the resulting compiled tree of data.
return nconf.get()
}

now i can use the above ./packages/config/index.js like so :

# in ./packages/web-server/index.js

function main () {
  # only loads the repo root config
  config = require('@us/config')()
}

or

# in ./packages/some_other_app/index.js

const HERE_DIR = __dirname;

function main () {
  # loads the repo root config, and what ever is in './settings'
  config = require('./services/config')([
    `${HERE_DIR}/settings`
  ])
}

Describe the solution you'd like

In my actualy use case we're using fastlane to build out our android and ios apps.

we have the bulk of the fastlane logic in a place like /packages/fastlane/Fastfile where this code below exists.

class OurConfig < Anyway::Config
  config_name :our_config
  env_prefix :our_config # now variables, starting wih `OUR_CONFIG_`, will be parsed

  Anyway::Settings.default_config_path = __dir__
  Anyway::Settings.extra_config_paths = [
    Dir.pwd()
  ]
end

then in our individual apps at places like /apps/hungarian_phrase_book/fastlane/Fastfile we import the above Fastfile and I'm expecting it to load both the /apps/hungarian_phrase_book/fastlane/config/whatever.yml and merge it all whilst also allowing for any value to be overridden from ENVVARS as usual.

Describe alternatives you've considered

the global gem , lets me source different files like I want, but doesn't allow for overriding with ENVVARS. [dotenv] yeah nah.

airtonix commented 3 years ago

i think i'm going to use https://github.com/infochimps-labs/configliere

looks like it suits my needs exactly as nconf does.

palkan commented 3 years ago

Anyway Config's main idea is to separate sources from configs, i.e., the config class itself shouldn't know anything about how it is populated, it's up to the end user (or host application).

The host application can control the order and list the list of sources using the Data Loaders API:

# For example, move ENV loader after file loader
Anyway.loaders.delete :env
Anyway.loaders.insert_after :yml, :env, Anyway::Loaders::Env

We can add a simpler API for the above, say: Anyway.loaders.move :env, after: :yml or Anyway.loaders.reorder(:yml, :env).

Though multiple config paths would require writing a custom loader for now or making YML loader recognize Array config_path (which sounds like a good idea).