CIでRSpecを回したかった
初めての GitHub Actions 導入でした。
コード
# .github/workflows/ci.yml
job:
test:
runs-on: ubuntu-latest
# postgresqlのDBコンテナを作成
services:
postgres:
image: postgres:17.0
ports:
- 5432:5432
env:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: database
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
RAILS_ENV: test
# database.yml で使用するため
DATABASE_HOST: postgres
DATABASE_USER: user
DATABASE_PASSWORD: password
DATABASE_NAME: database
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install packages
run: sudo apt-get update && sudo apt-get install -y libvips libpq-dev
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Setup database
run: bin/rails db:prepare
- name: Run RSpec
run: bundle exec rspec
- name: Keep screenshots from failed system tests
uses: actions/upload-artifact@v4
if: failure()
with:
name: screenshots
path: ${{ github.workspace }}/tmp/screenshots
if-no-files-found: ignore
host の指定が間違っていて DB に接続できない
Setup databaseのステップで、host: postgres のホスト名が解決できないらしくて落ちる
Run bin/rails db:prepare
bin/rails aborted!
ActiveRecord::DatabaseConnectionError: There is an issue connecting with your hostname: postgres. (ActiveRecord::DatabaseConnectionError)
Please check your database configuration and ensure there is a valid connection to your database.
ChatGPTに脳死で従ったら沼った
以下ChatGPTの説明↓↓↓↓
✅ 説明
GitHub Actions で services.postgres を定義した場合、ホスト名はサービス名(例:postgres)で解決されます。そのため、アプリケーション側(database.ymlなど)では host: postgres と記述すべきです。
✅ すべき実装(例:正しい database.yml の test セクション)
test:
adapter: postgresql
encoding: unicode
host: postgres # ✅ services の名前と一致
username: user
password: password
database: test
❌ すべきでない実装
# ❌ localhost や 127.0.0.1 を指定している例
test:
adapter: postgresql
encoding: unicode
host: localhost # ❌ GitHub Actions の service とは別世界
username: user
password: password
database: test
✅ 補足
host: postgres は、services: の postgres: というキー名による DNS 解決です。
ChatGPTが言ってるhost: postgres じゃダメだった(今回のような実装の場合)
参考
原因
GitHub Actions 実行時、DB ホスト名が localhost になっていませんでした。
公式ドキュメントにもサービスの DB への接続方法が記載されていました。
公式ドキュメント
You can access service containers from the Docker host using localhost and the Docker host port number.
host: localhost にしたら動いた
私が Docker のネットワークの仕組みを理解していないのが悪かったみたいでした。
serivce: で定義された DB は ホスト内のコンテナ上で動いており、一方で RSpec を回すジョブは直接ホスト上で動作しているので、ジョブから DB にアクセスするには localhost:<port> でアクセスすべき。
もしも container: などでジョブの方もコンテナ内で実行する場合は、DB とジョブは同じ Docker ネットワーク内に配置されるので、host: postgres のようにコンテナ名でホスト名解決ができる、とのことでした。
今思えば、ローカルで docker compose を立ち上げて、それに対してPCからlocalhost:3000 とかで接続するのと同じことだったのかな、と納得しました。
終わりに
よく理解していない部分を ChatGPT に頼ってしまうと、今回のようなよく知らないところでハルシネーションを起こした時にドツボにハマってしまうので、そういった部分はまずAI以外で確認してみることが重要だなと反省しました。