何かやってみるブログ

興味をもったこと、趣味のこと、技術について色々書きます。

[Goメモ] golang-migrateを使用してmigrateしたDBを使ったテストをGitHub Actionsで回す。

すっかり忘れてしまったHKT48のメンバーを思い出すために個人開発で簡単なクイズアプリを作成したとき golang-migate と GitHub Actionsを使うことがあったのでメモに残す。

以下が対象のリポジトリ github.com

golang-migrateについて

とりあえずローカルでgolang-migrate CLIを使用してmigrationを実行してみる。

基本的な使い方はいかに書かれているが念の為にメモに残しておく。

github.com

MySQLコンテナを立ち上げる。

 docker run --rm --name gin-service-db -e MYSQL_USER=ginuser \
        -e MYSQL_PASSWORD=password -e MYSQL_ROOT_PASSWORD=password \
        -e MYSQL_DATABASE=gin-service \
        -p 3307:3306 \
        --network gin-service-network\
        --hostname gin_service_db\
        -d  mysql:8.0

migrateを実行する

-databaseで先ほど立ち上げたMySQLコンテナを指定して -path で作成したマイグレーションファイルが入ったディレクトリを指定している。

migrate -database="mysql://ginuser:password@tcp(localhost:3307)/gin-service"\
                -path "./db/migrations"\
                --verbose up
2022/04/07 23:49:39 Start buffering 1/u init_db
2022/04/07 23:49:39 Start buffering 2/u init_data_form_csv
2022/04/07 23:49:39 Start buffering 3/u add_member_info_from_csv
2022/04/07 23:49:39 Read and execute 1/u init_db
2022/04/07 23:49:39 Finished 1/u init_db (read 129.465776ms, ran 254.94272ms)
2022/04/07 23:49:39 Read and execute 2/u init_data_form_csv
2022/04/07 23:49:39 Finished 2/u init_data_form_csv (read 487.425323ms, ran 171.378875ms)
2022/04/07 23:49:39 Read and execute 3/u add_member_info_from_csv
2022/04/07 23:49:40 Finished 3/u add_member_info_from_csv (read 771.780878ms, ran 198.832452ms)
2022/04/07 23:49:40 Finished after 999.447239ms
2022/04/07 23:49:40 Closing source and database

TablePlusで確認してみるときちんとテーブルが作成されているのが確認できる。

f:id:s-takaya1027:20220407234812p:plain

migrateを元に戻してみてみるときちんとテーブルが削除されていることが確認できる。

f:id:s-takaya1027:20220407235118p:plain

migrate -database="mysql://ginuser:password@tcp(localhost:3307)/gin-service"\
                -path "./db/migrations"\
                --verbose down
2022/04/07 23:48:40 Are you sure you want to apply all down migrations? [y/N]
y
2022/04/07 23:48:44 Applying all down migrations
2022/04/07 23:48:44 Start buffering 3/d add_member_info_from_csv
2022/04/07 23:48:44 Start buffering 2/d init_data_form_csv
2022/04/07 23:48:44 Start buffering 1/d init_db
2022/04/07 23:48:45 Read and execute 3/d add_member_info_from_csv
2022/04/07 23:48:45 Finished 3/d add_member_info_from_csv (read 346.478997ms, ran 242.207909ms)
2022/04/07 23:48:45 Read and execute 2/d init_data_form_csv
2022/04/07 23:48:45 Finished 2/d init_data_form_csv (read 690.487922ms, ran 132.063138ms)
2022/04/07 23:48:45 Read and execute 1/d init_db
2022/04/07 23:48:45 Finished 1/d init_db (read 976.37633ms, ran 190.032461ms)
2022/04/07 23:48:45 Finished after 5.236469304s
2022/04/07 23:48:45 Closing source and database

GitHub Actionsについて

GitHub Actionsで実行してみる。

定義ファイルは以下のようになっている。

name: Gin API

on:
  push:
    branches:
      - main

jobs:
  build:
    name: test
    runs-on: ubuntu-latest
    services:
      gin_service_db:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_USER: ginuser
          MYSQL_PASSWORD: password
          MYSQL_DATABASE: gin-service
          MYSQL_ROOT_PASSWORD: password
          MYSQL_HOST: gin_service_db
    steps:
    - uses: actions/checkout@v2
    - name: Set up Go
      uses: actions/setup-go@v2
      with:
        go-version: 1.17.7
    - name: Install golang-migrate CLI
      run: |
        curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | sudo apt-key add -
        echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/migrate.list
        sudo apt-get update
        sudo apt-get install -y migrate
    - name: Run Migration
      run: migrate -database="mysql://ginuser:password@tcp(localhost:3306)/gin-service" -path "./db/migrations" --verbose up
    - name: Build
      run: go build -v ./...
    - name: Test
      run: TEST_CLIENT=CI bash -c 'go test ./... -v'

以下のstepでgolang-migrate CLIをインストールしている。 インストール方法をこちらを参照した。

    - name: Install golang-migrate CLI
      run: |
        curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | sudo apt-key add -
        echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/migrate.list
        sudo apt-get update
        sudo apt-get install -y migrate

以下のstepでmigrateを実行している。

    - name: Run Migration
      run: migrate -database="mysql://ginuser:password@tcp(localhost:3306)/gin-service" -path "./db/migrations" --verbose up

Actionタブからmigrateされていることを確認できた。

f:id:s-takaya1027:20220408001442p:plain

以下のstepでテストを実行している。

    - name: Test
      run: TEST_CLIENT=CI bash -c 'go test ./... -v'

GitHub Actionsでハマったこと

MySQLサービスコンテナのホスト名の指定の方法が分からない

開発環境で使用しているMySQLコンテナのホスト名を gin_service_dbと命名してDSNを ginuser:password@tcp(gin_service_db:3306)/gin-service?parseTime=trueとして使用しているのでGitHub Actions上でもMySQLサービスコンテナに gin_service_dbというホスト名を付けたかったが分からなかったので、以下のように TEST_CLIENTという環境変数があるかどうかとその値が CIとなった時にCI用のDSN (ginuser:password@tcp(127.0.0.1:3306)/gin-service?parseTime=true) を返す関数を作成した。

func configTestCliant() string {
    if value, ok := os.LookupEnv("TEST_CLIENT"); ok && value == "CI" {
        return "ginuser:password@tcp(127.0.0.1:3306)/gin-service?parseTime=true"
    }
    return "ginuser:password@tcp(gin_service_db:3306)/gin-service?parseTime=true"
}

func ConnectDB() *sql.DB {
    var dnsNmae string = configTestCliant()
    db, err := sql.Open("mysql", dnsNmae)
    if err != nil {
        panic(err.Error())
    }

    return db
}