【Actions】DB 用のコンテナを用意する【GitHub】

ワークフロー中のタスクで、データベースに接続したいなというとき、「サービスコンテナ」を使用して DB 用のコンテナをホストすると、タスクからこのコンテナと通信することができます。例えば、Docker Compose で DB 用のコンテナを立ち上げていた場合、Actions のワークフローで DB 用のコンテナをサービスコンテナとして定義してあげることで、Actions 上でも DB を使用した結合テストを実行することができます。

https://docs.github.com/ja/actions/guides/about-service-containers

## サンプル

[GitHub Docs](https://docs.github.com/ja/actions/guides/creating-postgresql-service-containers)にサービスコンテナを使用したワークフローサンプルがあります。サンプルでは、Postgres をサービスコンテナとして定義して、Node アプリケーションから接続しにいっています。

```yaml:.github/workflows/main.yaml
name: PostgreSQL Service Example
on: push

jobs:
  # ランナージョブのラベル
  runner-job:
    # サービスコンテナまたはコンテナジョブを使用する場合は Linux 環境を使用する必要がある
    runs-on: ubuntu-latest

    # `runner-job` で実行されるサービスコンテナ
    services:
      # サービスコンテナへのアクセスに使用されるラベル
      postgres:
        # Docker Hub イメージ
        image: postgres
        # postgres のパスワードを入力する
        env:
          POSTGRES_PASSWORD: postgres
        # postgres が起動するまで待機するようにヘルスチェックを設定する
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # サービスコンテナの tcp ポート 5432 をホストにマップする
          - 5432:5432

    steps:
      # CI テストを実行する前に、リポジトリにコードのコピーをダウンロードする
      - name: Check out repository code
        uses: actions/checkout@v2

      # `package.json` ファイル内のすべての依存関係のクリーンインストールを実行する
      # 詳しい情報については https://docs.npmjs.com/cli/ci.html を参照する
      - name: Install dependencies
        run: npm ci

      - name: Connect to PostgreSQL
        # PostgreSQLテーブルを作成し、テーブルにデータを入力してから
        # データを取得するスクリプトを実行する
        run: node client.js
        # `client.js` スクリプトが新しいPostgreSQLクライアントの
        # 作成に使う環境変数
        env:
          # PostgreSQLサービスコンテナとの通信に使われるホスト名
          POSTGRES_HOST: localhost
          # デフォルトのPostgreSQLポート
          POSTGRES_PORT: 5432
```

Node アプリケーション

```javascript:client.js
const { Client } = require('pg');

const pgclient = new Client({
    host: process.env.POSTGRES_HOST,
    port: process.env.POSTGRES_PORT,
    user: 'postgres',
    password: 'postgres',
    database: 'postgres'
});

pgclient.connect();

const table = 'CREATE TABLE student(id SERIAL PRIMARY KEY, firstName VARCHAR(40) NOT NULL, lastName VARCHAR(40) NOT NULL, age INT, address VARCHAR(80), email VARCHAR(40))'
const text = 'INSERT INTO student(firstname, lastname, age, address, email) VALUES($1, $2, $3, $4, $5) RETURNING *'
const values = ['Mona the', 'Octocat', 9, '88 Colin P Kelly Jr St, San Francisco, CA 94107, United States', 'octocat@github.com']

pgclient.query(table, (err, res) => {
    if (err) throw err
});

pgclient.query(text, values, (err, res) => {
    if (err) throw err
});

pgclient.query('SELECT * FROM student', (err, res) => {
    if (err) throw err
    console.log(err, res.rows) // Print the data in student table
    pgclient.end()
});
```

``pg``モジュールが必要なので、``package.json``も用意しておきます。

```json:package.json
{
  "name": "service-container-sample",
  "version": "1.0.0",
  "description": "",
  "main": "client.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "pg": "^8.7.1"
  }
}
```

## 注意

現在(2021/9/4時点)のところ Actions をローカル実行できる``act``ではまだ、サービスコンテナに対応しておりません[^1]。``act``にはまだ対応していない Actions の機能がまだまだたくさんありますので、``act``の今後の開発状況に注目です。

[^1]: https://github.com/nektos/act/issues/173