README.md in ejson-rails-0.1.1 vs README.md in ejson-rails-0.2.0
- old
+ new
@@ -1,10 +1,10 @@
# EJSON::Rails
-[![Build Status](https://travis-ci.com/Shopify/ejson-rails.svg?token=ShuwwQhmf65yNstgcUSy&branch=master)](https://travis-ci.com/Shopify/ejson-rails)
+[![Build Status](https://github.com/Shopify/ejson-rails/workflows/CI/badge.svg?branch=main)](https://github.com/Shopify/ejson-rails/actions?query=branch%3Amain)
-Automatically injects `ejson` decrypted secrets into your `Rails.application.secrets`.
+Automatically injects [`ejson`](https://github.com/Shopify/ejson) decrypted secrets into your `Rails.application.secrets`.
## Installation
Add this line to your application's Gemfile:
@@ -28,9 +28,98 @@
// project/config/secrets.json
{ "some_secret": "key" }
```
will be accessible via `Rails.application.secrets.some_secret` or `Rails.application.secrets[:some_secret]` on boot. JSON files are loaded once and contents are `deep_merge`'d into your app's existing rails secrets.
+
+Secrets will also be accessible via `Rails.application.credentials`, e.g. `Rails.application.credentials.some_secret` or `Rails.application.credentials[:some_secret]`. To avoid subtle compatibility issues, if a credential already exists, an error will occur.
+
+NOTE: This gem does not decrypt ejson for you. You will need to configure this as part of your deployment pipeline.
+
+## Migrating to credentials
+
+Rails 7.1 has deprecated application secrets in favor of credentials. ejson-rails can migrate secrets to application credentials.
+
+Even before running Rails 7.1, you can migrate your secrets in a few steps.
+
+First, move the development and test secrets to JSON secrets:
+
+```sh-session
+bin/rails runner 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
+bin/rails runner -e test 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
+```
+
+Secrets support ERB while EJSON secrets don't, so if your secrets contain ERB, you will need to move that logic to the environment configurations:
+
+**Before**:
+
+`config/secrets.yml`
+```yaml
+development:
+ some_external_service:
+ api_token: <%= ENV.fetch(SOME_EXTERNAL_SERVICE_API_TOKEN, "12345") %>
+```
+
+**After**:
+
+`config/secrets.development.json` as generated by the command above.
+```json
+{
+ "some_external_service": {
+ "api_token": "12345"
+ },
+ "something_else_entirely": "abc"
+}
+```
+
+`config/environments/development.rb`
+```ruby
+Rails.application.configure do
+ # elided
+
+ # credential should be set using []=, not the dynamic accessors
+ credentials[:some_external_service][:api_token] = ENV.fetch("SOME_EXTERNAL_SERVICE_API_TOKEN", "12345")
+
+ # top-level values must be set through `credentials.config`
+ credentials.config[:something_else_entirely] = ENV.fetch("SOMETHING_ELSE_ENTIRELY", "abc")
+end
+```
+
+Note that the code accesses the credentials as a Hash with `[]` and `[]=`. This is important because the dynamic accessor methods will set values in a different object, and credentials will behave inconsistently after that:
+
+```ruby
+Rails.application.credentials.some_external_service.api_token = "foo"
+Rails.application.credentials[:some_external_service][:api_token] # => "12345"
+```
+
+Also note the code sets top-level values through `credentials.config`, because `credentials#[]=(key, value)` sets values in a different object.
+
+```ruby
+Rails.application.credentials[:something_else_entirely] = "foo"
+Rails.application.credentials[:something_else_entirely] # => "abc"
+```
+
+Make sure there's no code using the dynamic accessors before setting the configuration in the Hash, or the values won't be accessible from the dynamic accessor:
+
+```ruby
+Rails.application.credentials.something_else_entirely # just accessing is enough to cause the issue
+Rails.application.credentials[:some_external_service][:api_token] = "foo"
+Rails.application.credentials.some_external_service.api_token # => "12345"
+```
+
+You're now ready to use credentials instead of secrets:
+
+```sh-session
+git ls-files | xargs ruby -pi -e 'gsub("Rails.application.secrets", "Rails.application.credentials")' --
+```
+
+To avoid the deprecation warning from the use of secrets in `ejson-rails` once you're running Rails 7.1, require another file from your Gemfile:
+
+```ruby
+gem 'ejson-rails', require: 'ejson/rails/skip_secrets'
+```
+
+This will no longer merge secrets from JSON in `Rails.application.secrets`. This will be the default in the next major version.
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.