Rails credential values are nil while running tests on github actions

Viewed 819

I am encoding and decoding JSON web tokens using Rails secret_key_base, my secret_key_base is in the credentials.yml.enc file. In one of the test, I am using this function to decode JWT,locally the tests are running fine but on github action it is failing, I found out the the value of Rails.application.crendentials.secret_key_base is nil when running the test on github action. I fixed those tests by mocking like this

    allow(Rails.application.credentials).to receive(:secret_key_base).
      and_return("secret")

Is there a way I don't have to do this on github action for other credentials. Also since the master.key was not committed I hoped that I would see this error

ActiveSupport::MessageEncryptor::InvalidMessage

while reading from the credentials file but that also didn't happen. This is a link to my project if that clears things up.

2 Answers

In Rails 6, you can create credentials.yml.enc file per environment.

In vscode:

EDITOR="code --wait" rails credentials:edit --environment production
EDITOR="code --wait" rails credentials:edit --environment test

it gives you production.key, production.yml.enc, test.key, test.yml.enc. You can then commit test.key to github for testing or even better, set this key in RAILS_TEST_KEY env.

Though it gets a little bit tricky to maintain both env files. You can create credenetials.yml.example file with empty envs for reference

I think 'the cleanest/right way' to do this is to add master key(value from config/master.key) into github secrets.

Go to repository settings->secrets(left side menu)->new repository secret. It makes sense to name it RAILS_MASTER_KEY. And then in your workflow file add

env:
  RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}

And that's it, Rails will be smart enough to use that variable in credentials decryption.

No need to make additional credentials files. For me it's working with only one credentials.yml.enc

EDIT: Even better, if you can skip using credentials, add heroku config variable SECRET_KEY_BASE and in config/application.rb add

config.secret_key_base = ENV['SECRET_KEY_BASE']

and for production use Rails.configuration.secret_key_base, for test/development Rails.application.secrest.secret_key_base that's set by rails

ex.

SECRET_KEY = Rails.env.production? ? Rails.configuration.secret_key_base : Rails.application.secrets.secret_key_base

This way you don't have to store master key on every machine that's running your app. ex. coworkers, github actions, staging, production.

Related