{"id":13483625,"url":"https://github.com/railsware/global","last_synced_at":"2025-05-16T13:08:01.978Z","repository":{"id":9590775,"uuid":"11509317","full_name":"railsware/global","owner":"railsware","description":"\"Global\" provides accessor methods for your configuration data","archived":false,"fork":false,"pushed_at":"2024-12-04T11:14:15.000Z","size":157,"stargazers_count":283,"open_issues_count":0,"forks_count":15,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-04-12T10:57:47.987Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://railsware.github.io/global","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/railsware.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2013-07-18T17:37:51.000Z","updated_at":"2025-03-03T05:54:33.000Z","dependencies_parsed_at":"2025-04-12T09:32:45.660Z","dependency_job_id":"4669ecff-2567-4c21-8dab-c10e35427ba3","html_url":"https://github.com/railsware/global","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2Fglobal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2Fglobal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2Fglobal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2Fglobal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/railsware","download_url":"https://codeload.github.com/railsware/global/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253860124,"owners_count":21975219,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T17:01:13.471Z","updated_at":"2025-05-16T13:08:01.948Z","avatar_url":"https://github.com/railsware.png","language":"Ruby","readme":"# Global [![Runs linter and tests](https://github.com/railsware/global/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/railsware/global/actions/workflows/tests.yml) [![Code Climate](https://codeclimate.com/github/railsware/global.png)](https://codeclimate.com/github/railsware/global)\n\nThe 'global' gem provides accessor methods for your configuration data and share configuration across backend and frontend.\n\nThe data can be stored in [YAML](https://yaml.org) files on disk, or in the [AWS SSM Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html).\n\n## Installation\n\nAdd to Gemfile:\n\n```ruby\ngem 'global'\n```\n\nRefer to the documentation on your chosen backend class for other dependencies.\n\n## Configuration\n\nRefer to the documentation on your chosen backend class for configuration options.\n\n```ruby\n\u003e Global.backend(:filesystem, environment: \"YOUR_ENV_HERE\", path: \"PATH_TO_DIRECTORY_WITH_FILES\")\n```\n\nOr you can use `configure` block:\n\n```ruby\nGlobal.configure do |config|\n  config.backend :filesystem, environment: \"YOUR_ENV_HERE\", path: \"PATH_TO_DIRECTORY_WITH_FILES\"\n  # set up multiple backends and have them merged together:\n  config.backend :aws_parameter_store, prefix: '/prod/MyApp/'\n  config.backend :gcp_secret_manager, prefix: 'prod-myapp-', project_id: 'example'\nend\n```\n\n### Using multiple backends\n\nSometimes it is practical to store some configuration data on disk (and perhaps, commit it to source control), but\nkeep some other data in a secure remote location. Which is why you can use more than one backend with Global.\n\nYou can declare as many backends as you want; the configuration trees from the backends are deep-merged together,\nso that the backend declared later overwrites specific keys in the backend declared prior:\n\n```ruby\nGlobal.configure do |config|\n  config.backend :foo # loads tree { credentials: { hostname: 'api.com', username: 'dev', password: 'dev' } }\n  config.backend :bar # loads tree { credentials: { username: 'xxx', password: 'yyy' } }\nend\n\nGlobal.credentials.hostname # =\u003e 'api.com'\nGlobal.credentials.username # =\u003e 'xxx'\nGlobal.credentials.password # =\u003e 'yyy'\n```\n\nFor Rails, put initialization into `config/initializers/global.rb`.\n\nThere are some sensible defaults, check your backend class for documentation.\n\n```ruby\nGlobal.configure do |config|\n  config.backend :filesystem\nend\n```\n\n### Filesystem storage\n\nThe `yaml_whitelist_classes` configuration allows you to deserialize other classes from your `.yml`\n\n### AWS Parameter Store\n\nThe `aws_options` configuration allows you to customize the AWS credentials and connection.\n\n### Google Cloud Secret Manager\n\nThe `gcp_options` configuration allows you to customize the Google Cloud credentials and timeout.\n\n## Usage\n\n### Filesystem\n\nFor file `config/global/hosts.yml`:\n\n```yml\ntest:\n  web: localhost\n  api: api.localhost\ndevelopment:\n  web: localhost\n  api: api.localhost\nproduction:\n  web: myhost.com\n  api: api.myhost.com\n```\n\nIn the development environment we now have:\n\n```ruby\n\u003e Global.hosts\n=\u003e { \"api\" =\u003e \"api.localhost\", \"web\" =\u003e \"localhost\" }\n\u003e Global.hosts.api\n=\u003e \"api.localhost\"\n```\n\n#### Deserialize other classes from `.yml`\n\nConfig file `config/global/validations.yml`:\n\n```yml\ndefault:\n  regexp:\n    email: !ruby/regexp /.@.+\\../\n```\n\nEnsure that `Regexp` is included in the `yaml_whitelist_classes` array\n\n```ruby\nGlobal.validations.regexp.email === 'mail@example.com'\n=\u003e true\n```\n\n#### Per-environment sections\n\nYou can define environment sections at the top level of every individual YAML file\n\nFor example, having a config file `config/global/web/basic_auth.yml` with:\n\n```yml\ntest:\n  username: test_user\n  password: secret\ndevelopment:\n  username: development_user\n  password: secret\nproduction:\n  username: production_user\n  password: supersecret\n```\n\nYou get the correct configuration in development\n\n```ruby\n\u003e Global.web.basic_auth\n=\u003e { \"username\" =\u003e \"development_user\", \"password\" =\u003e \"secret\" }\n\u003e Global.web.basic_auth.username\n=\u003e \"development_user\"\n```\n\n#### Default section\n\nConfig file example:\n\n```yml\ndefault:\n  web: localhost\n  api: api.localhost\nproduction:\n  web: myhost.com\n  api: api.myhost.com\n```\n\nData from the default section is used until it's overridden in a specific environment.\n\n#### Nested configurations\n\nConfig file `global/nested.yml` with:\n\n```yml\ntest:\n  group:\n    key: \"test value\"\ndevelopment:\n  group:\n    key: \"development value\"\nproduction:\n  group:\n    key: \"production value\"\n```\n\nNested options can then be accessed as follows:\n\n```ruby\n\u003e Global.nested.group.key\n=\u003e \"development value\"\n```\n\n#### Environment files\n\nConfig file `global/aws.yml` with:\n```yml\n:default:\n  activated: false\n\nstaging:\n  activated: true\n  api_key: 'nothing'\n\n```\n\nAnd file `global/aws.production.yml` with:\n```yml\n:activated: true\n:api_key: 'some api key'\n:api_secret: 'some secret'\n\n```\n\nProvide such configuration on `Global.environment = 'production'` environment:\n\n```ruby\n\u003e Global.aws.activated\n=\u003e true\n\u003e Global.aws.api_key\n=\u003e 'some api key'\n\u003e Global.aws.api_secret\n=\u003e 'some secret'\n```\n\n**Warning**: files with dot(s) in name will be skipped by Global (except this env files).\n\n#### ERB support\n\nConfig file `global/file_name.yml` with:\n\n```yml\ntest:\n  key: \u003c%=1+1%\u003e\ndevelopment:\n  key: \u003c%=2+2%\u003e\nproduction:\n  key: \u003c%=3+3%\u003e\n```\n\nAs a result, in the development environment we have:\n\n```ruby\n\u003e Global.file_name.key\n=\u003e 4\n```\n\n### AWS Parameter Store\n\nParameter Store is a secure configuration storage with at-rest encryption. Access is controlled through AWS IAM. You do not need to be hosted on AWS to use Parameter Store.\n\nRefer to the [official documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) to set up the store.\n\nSome steps you will need to follow:\n\n- Allocate an AWS IAM role for your app.\n- Create an IAM user for the role and pass credentials in standard AWS env vars (applications on Fargate get roles automatically).\n- Choose a prefix for the parameters. By default, the prefix is `/environment_name/AppClassName/`. You can change it with backend parameters (prefer to use '/' as separator).\n- Allow the role to read parameters from AWS SSM. Scope access by the prefix that you're going to use.\n- If you will use encrypted parameters: create a KMS key and allow the role to decrypt using the key.\n- Create parameters in Parameter Store. Use encryption for sensitive data like private keys and API credentials.\n\n#### Usage with Go\n\nYou can reuse the same configuration in your Go services. For this, we developed a Go module that loads the same configuration tree into Go structs.\n\nSee [github.com/railsware/go-global](https://github.com/railsware/go-global) for further instructions.\n\n#### Configuration examples\n\nBackend setup:\n\n```ruby\n# in config/environments/development.rb\n# you don't need to go to Parameter Store for dev machines\nGlobal.backend(:filesystem)\n\n# in config/environments/production.rb\n# enterprise grade protection for your secrets\nGlobal.backend(:aws_parameter_store, app_name: 'my_big_app')\n```\n\nCreate parameters:\n\n```\n/production/my_big_app/basic_auth/username =\u003e \"bill\"\n/production/my_big_app/basic_auth/password =\u003e \"secret\" # make sure to encrypt this one!\n/production/my_big_app/api_endpoint =\u003e \"https://api.myapp.com\"\n```\n\nGet configuration in the app:\n\n```ruby\n# Encrypted parameters are automatically decrypted:\n\u003e Global.basic_auth.password\n=\u003e \"secret\"\n\u003e Global.api_endpoint\n=\u003e \"https://api.myapp.com\"\n```\n\n### Google Cloud Secret Manager\n\nGoogle Cloud Secret Manager allows you to store, manage, and access secrets as binary blobs or text strings. With the appropriate permissions, you can view the contents of the secret.\nGoogle Cloud Secret Manager works well for storing configuration information such as database passwords, API keys, or TLS certificates needed by an application at runtime.\n\nRefer to the [official documentation](https://cloud.google.com/secret-manager/docs) to set up the secret manager.\n\nSome steps you will need to follow:\n\n- Choose a prefix for the secret key name. By default, the prefix is `environment_name-AppClassName-`. You can change it with backend parameters (prefer to use '-' as separator).\n\n#### Configuration examples\n\nBackend setup:\n\n```ruby\n# in config/environments/development.rb\n# you don't need to go to Parameter Store for dev machines\nGlobal.backend(:filesystem)\n\n# in config/environments/production.rb\n# enterprise grade protection for your secrets\nGlobal.backend(:gcp_secret_manager, prefix: 'prod-myapp-', project_id: 'example')\n```\n\nCreate secrets:\n\n```\nprod-myapp-basic_auth-username =\u003e \"bill\"\nprod-myapp-basic_auth-password =\u003e \"secret\"\nprod-myapp-api_endpoint =\u003e \"https://api.myapp.com\"\n```\n\nGet configuration in the app:\n\n```ruby\n# Encrypted parameters are automatically decrypted:\n\u003e Global.basic_auth.password\n=\u003e \"secret\"\n\u003e Global.api_endpoint\n=\u003e \"https://api.myapp.com\"\n```\n\n### Reload configuration data\n\n```ruby\n\u003e Global.reload!\n```\n\n## Using YAML configuration files with Rails Webpacker\n\nIf you use the `:filesystem` backend, you can reuse the same configuration files on the frontend:\n\nAdd [js-yaml](https://www.npmjs.com/package/js-yaml) npm package to `package.json` (use command `yarn add js-yaml`).\n\nThen create a file at `config/webpacker/global/index.js` with the following:\n\n```js\nconst yaml = require('js-yaml')\nconst fs = require('fs')\nconst path = require('path')\n\nconst FILE_ENV_SPLIT = '.'\nconst YAML_EXT = '.yml'\n\nlet globalConfig = {\n  environment: null,\n  configDirectory: null\n}\n\nconst globalConfigure = (options = {}) =\u003e {\n  globalConfig = Object.assign({}, globalConfig, options)\n}\n\nconst getGlobalConfig = (key) =\u003e {\n  let config = {}\n  const filename = path.join(globalConfig.configDirectory, `${key}${YAML_EXT}`)\n  if (fs.existsSync(filename)) {\n    const configurations = yaml.safeLoad(fs.readFileSync(filename, 'utf8'))\n    config = Object.assign({}, config, configurations['default'] || {})\n    config = Object.assign({}, config, configurations[globalConfig.environment] || {})\n\n    const envFilename = path.join(globalConfig.configDirectory, `${key}${FILE_ENV_SPLIT}${globalConfig.environment}${YAML_EXT}`)\n    if (fs.existsSync(envFilename)) {\n      const envConfigurations = yaml.safeLoad(fs.readFileSync(envFilename, 'utf8'))\n      config = Object.assign({}, config, envConfigurations || {})\n    }\n  }\n  return config\n}\n\nmodule.exports = {\n  globalConfigure,\n  getGlobalConfig\n}\n```\n\nAfter this, modify file `config/webpacker/environment.js`:\n\n```js\nconst path = require('path')\nconst {environment} = require('@rails/webpacker')\nconst {globalConfigure, getGlobalConfig} = require('./global')\n\nglobalConfigure({\n  environment: process.env.RAILS_ENV || 'development',\n  configDirectory: path.resolve(__dirname, '../global')\n})\n\nconst sentrySettings = getGlobalConfig('sentry')\n\nenvironment.plugins.prepend('Environment', new webpack.EnvironmentPlugin({\n  GLOBAL_SENTRY_ENABLED: sentrySettings.enabled,\n  GLOBAL_SENTRY_JS_KEY: sentrySettings.js,\n  ...\n}))\n\n...\n\nmodule.exports = environment\n```\n\nNow you can use these `process.env` keys in your code:\n\n```js\nimport {init} from '@sentry/browser'\n\nif (process.env.GLOBAL_SENTRY_ENABLED) {\n  init({\n    dsn: process.env.GLOBAL_SENTRY_JS_KEY\n  })\n}\n```\n\n## Contributing to global\n\n* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.\n* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.\n* Fork the project.\n* Start a feature/bugfix branch.\n* Commit and push until you are happy with your contribution.\n* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.\n* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.\n\nThis project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/railsware/global/blob/master/CODE_OF_CONDUCT.md).\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Global project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/railsware/global/blob/master/CODE_OF_CONDUCT.md).\n","funding_links":[],"categories":["Configuration","Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsware%2Fglobal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frailsware%2Fglobal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsware%2Fglobal/lists"}