Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【GitHub Actions・Rails】NoMethodError: Cannot load database configuration: undefined method `[]' for nil:NilClass

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. 原因

ここら辺を参考。

要は、例えば以下の場合、

<%= 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 で、リポジトリに秘匿情報を設定することができます。

スクリーンショット 2020-11-23 17.07.39.png

config/master.key の値を入力します(改行やスペースを含めてしまうとうまくいかないかもしれません)。

スクリーンショット 2020-11-23 17.08.52.png

スクリーンショット 2020-11-23 17.09.12.png

上記で設定した秘匿情報は、 ${{ 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: asima_test

解決策3. Rails.application.credentials.hoge[:fuga]を呼ばない

ymlファイルでもif文を書ける。

# config/database.yml
...
production:
  <<: *default
  <% if Rails.application.credentials.database.present? %>
    database: asima_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

参考になれば幸いです。

yokoto
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away