🚏

GitHub Actions内でPostgresを起動しつつ、起動するまで待つ

2024/02/17に公開

やりたいこと

GitHub Actions内でテストを実行する都合上、DBを起動したいです。DBにはPostgresを使います。

ざっくり以下のような感じでActionsを作っていきたいと思ったわけです。

  1. docker compose up db -d
  2. docker compose exec db psql -c "テストデータを入れるSQL"
  3. テスト実行
  4. docker compose down

しかし、2でまだDBが起動しとらんよ、というエラーが発生し、こけてしまったのでした。
そこで、DBが起動するまで待つ処理を頑張って編み出したので紹介します。

やりかた

まずは答えです。
あとで、それぞれやっていることを解説します。

- name: Up db and wait for ready
  run: |
    docker compose up db -d
    set +e
    for (( i=0; i<10; ++i )); do
      docker compose exec db pg_isready
      if [ $? -eq 0 ]; then
        break
      fi
      sleep 1;
    done

DBが起動しているかを調べる

pg_isready というコマンドがあります。こいつは、Postgresがreadyかどうか調べてくれる大変スグレモノです。

docker compose exec db pg_isready を実行すると、DBが起動していればEXIT STATUS=0になりますし、起動していなければEXIT STATUS=2になります。

コマンドのオプションに --timeout というのがあるのですが、少なくとも今回の用途には使えませんでした。起動していない場合は何を指定しても、 no response と出て一瞬でエラーになります。最低限コネクションは張れる前提ということなんでしょうか。

起動するまで待つようにする

タイムアウトが効かないのであれば、DBが起動するまで pg_isready をポーリングすればよいでしょう。無限ループにならないようにforループを使います。

しかし、これだけだと、GitHub Actionsでは使えません。ステータスコードが0以外になった瞬間にGitHub Actionsはエラーになって終了してしまいます。

GitHub Actionsでエラーになっても終了しないようにする

set +e を使います。 set -e はスクリプトが途中でエラーになったら以降処理を行わない、という意味ですが、それの逆をやってくれるコマンドです。

GitHub Actionsではデフォルトで set -e が有効になっているため、 set +e で無効にしてあげる必要があります。

まとめ

Postgresが有効になるまで待つためにいろいろ引っかかったのですが、解決方法がググっても出てこずわりと困りました。
ChatGPTに聞いて set +e で回避できることを知るなどしました。

以上です。よろしくお願いします。

Discussion