【GitHub Actions】ChatGPTに従ってRSpecのCIを組んだらハマった話

# CIでRSpecを回したかった
初めての GitHub Actions 導入でした。

## コード
```yml
# .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 セクション）

```yaml
test:
  adapter: postgresql
  encoding: unicode
  host: postgres         # ✅ services の名前と一致
  username: user
  password: password
  database: test
```
❌ すべきでない実装
```yaml
# ❌ 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 への接続方法が記載されていました。

https://qiita.com/mkin/items/43682481758033d8685d


### 公式ドキュメント
> You can access service containers from the Docker host using localhost and the Docker host port number.

https://docs.github.com/en/actions/use-cases-and-examples/using-containerized-services/creating-postgresql-service-containers#running-jobs-directly-on-the-runner-machine

## host: localhost にしたら動いた
私が Docker のネットワークの仕組みを理解していないのが悪かったみたいでした。

`serivce:` で定義された DB は ホスト内のコンテナ上で動いており、一方で RSpec を回すジョブは直接ホスト上で動作しているので、ジョブから DB にアクセスするには `localhost:<port>` でアクセスすべき。

もしも `container:` などでジョブの方もコンテナ内で実行する場合は、DB とジョブは同じ Docker ネットワーク内に配置されるので、`host: postgres` のようにコンテナ名でホスト名解決ができる、とのことでした。

今思えば、ローカルで `docker compose` を立ち上げて、それに対してPCから`localhost:3000` とかで接続するのと同じことだったのかな、と納得しました。

## 終わりに
よく理解していない部分を ChatGPT に頼ってしまうと、今回のようなよく知らないところでハルシネーションを起こした時にドツボにハマってしまうので、そういった部分はまずAI以外で確認してみることが重要だなと反省しました。