0. 問題
rails db:create
または rails db:migrate
が途中で失敗してしまう。
エラーログは以下のような、ちょっと根深そうな感じ。
$ bundle exec rake db:create
rake aborted!
NoMethodError: Cannot load database configuration:
undefined method `[]' for nil:NilClass
(erb):20:in `<main>'
hoge/fuga/app/models/application_record.rb:1:in `<main>'
...
/opt/hostedtoolcache/Ruby/2.7.2/x64/bin/bundle:23:in `load'
/opt/hostedtoolcache/Ruby/2.7.2/x64/bin/bundle:23:in `<main>'
Tasks: TOP => db:create => db:load_config => environment
(See full trace by running task with --trace)
Error: Process completed with exit code 1.
application_record.rbの1行目で発生しているのでどういうことなのか、、
1. 原因
ここら辺を参考。
- 何度やってもNill class、原因不明のmigrate faild、問題はcredentials.yml.encが握っていた。
- 【Rails】rails sを実行すると「Cannot load database configuration」とエラーが出て強制終了される
- cannot load 'rails.application.database_configuration' undefined method'[]' for nil:NilClass
要は、例えば以下の場合、
<%= Rails.application.credentials.database[:host] %>
のようにcredentials.yml.encの秘匿情報を呼び出している記述で、
Rails.application.credentials.database
が空になってしまっているため、
[:host]
が呼び出せず、
undefined method '[]' for nil:NilClass
が発生してしまう。
Rails.application.credentials.database
が空になってしまうのは環境依存の問題で、
GitHub Actions上のUbuntu仮想環境であるせいで credentials.yml.enc を見れない。
GitHub Actions側で秘匿情報の設定をする必要があったため。
2. 解決策
今回の例では、config/database.ymlで定義された
Rails.application.credentials.database[:host]
を呼べるようにするか、呼ばなければ良い。
以下のいずれかを適用すれば通るようになる。
解決策1. GitHubリポジトリ上で RAILS_MASTER_KEY
を設定する
GitHub Actionsを設定している、GitHubリポジトリ上で
Settings > Secrets
で、リポジトリに秘匿情報を設定することができます。
config/master.key
の値を入力します(改行やスペースを含めてしまうとうまくいかないかもしれません)。
上記で設定した秘匿情報は、 ${{ secrets.設定した名前 }}
として、GitHub Actionsの設定ファイルから呼び出すことができます。
# 例
...
- name: Run tests
env:
RAILS_ENV: test
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
run: bundle exec rspec
...
これにより、GitHub Actionsの環境上で、 Rails.application.credentials
を見ることができるようになります。
参考
解決策2. database.yml.ci を作成・使用する
# .github/workflows/ruby.yml
...
- name: Setup test database
env:
RAILS_ENV: test
run: |
cp config/database.yml.ci config/database.yml
bundle exec rake db:create
bundle exec rake db:migrate
...
# config/database.yml.ci
default: &default
adapter: mysql2
encoding: utf8mb4
charset: utf8mb4
collation: utf8mb4_general_ci
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: 127.0.0.1
port: 3306
username: root
password:
test:
<<: *default
database: sample_app_test
解決策3. Rails.application.credentials.hoge[:fuga]を呼ばない
ymlファイルでもif文を書ける。
# config/database.yml
...
production:
<<: *default
<% if Rails.application.credentials.database.present? %>
database: sample_app_production
host: <%= Rails.application.credentials.database[:host] %>
username: <%= Rails.application.credentials.database[:username] %>
password: <%= Rails.application.credentials.database[:password] %>
<% end %>
<% if Rails.env.production? %>
でも良いかも。
3. GitHub Actions設定ファイル
一旦こんな感じになりました。
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
name: Rails Tests
on: push
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:5.7
env:
MYSQL_USER: root
MYSQL_ALLOW_EMPTY_PASSWORD: yes
BIND-ADDRESS: 0.0.0.0
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -h localhost"
--health-interval 20s
--health-timeout 10s
--health-retries 10
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Ruby 2.7
uses: actions/setup-ruby@v1
with:
ruby-version: 2.7
- name: Cache gems
uses: actions/cache@preview
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-
- name: Cache node modules
uses: actions/cache@preview
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- name: bundle install
run: |
gem install bundler
bundle install --jobs 4 --retry 3 --path vendor/bundle
- name: yarn install
run: yarn install --check-files
- name: Setup test database
env:
RAILS_ENV: test
run: |
cp config/database.yml.ci config/database.yml
bundle exec rake db:setup
- name: Run Lint
run: bundle exec rubocop
- name: Run tests
env:
RAILS_ENV: test
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
run: bundle exec rspec
参考になれば幸いです。