ent. と atlasを用いたバージョン管理型マイグレーションのやり方
1. はじめに
GolangでORMを使うなら ent. がおすすめ!の記事で、ent.の紹介をした続きになります。
前回は、atlasを利用したバージョン管理型マイグレーションのやり方を説明せずに省いたので、今回はその紹介になります。
atlasについての説明やスキーマの可視化については、ent. と atlas を利用したスキーマの可視化で説明しているので、よければ読んでみて下さい!
2. 開発環境
以下に、筆者の開発環境と本記事で利用するリポジトリを記載します。
- golang v1.21.4
- docker 4.16.2
- postgresql 16.1
- ent. v0.12.5
- atlas v0.15.1-04e0010-canary
3. atlasを利用したマイグレーションのバージョン管理
今回は、ent.のQuick Introductionの内容に対して、マイグレーションのバージョン管理を行おうと思います!
以前の記事で、ent.についてはある程度説明しているので、冗長な箇所はサクッと説明していきます。
3-1. atlasのインストール
まずは、atlasのインストールしましょう。
私は以下のようにbrewを利用してインストールしました。
$ brew install ariga/tap/atlas
brew以外の方法でインストールしたい方は、installationを参照して下さい。
インストールが完了したら、以下のようにコマンドが動作するか確認しておきましょう。
$ atlas -h
正常にインストールが完了していると、以下のように出力されます。
沢山コマンドがありますが、主に利用するのはmigrate
コマンドになります。
A database toolkit.
Usage:
atlas [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
license Display license information
login Log in to Atlas Cloud.
logout Logout from Atlas Cloud.
migrate Manage versioned migration files
schema Work with atlas schemas.
version Prints this Atlas CLI version information.
Flags:
-h, --help help for atlas
Use "atlas [command] --help" for more information about a command.
3-2. Userスキーマの作成
以下の順序で、Userスキーマを作成します。
今回の学習用のディレクトリを作成し、Userスキーマを作成します。
$ mkdir entdemo_versioned
$ cd entdemo_versioned
$ go mod init entdemo
$ go run -mod=mod entgo.io/ent/cmd/ent new User
生成されたuser.go
に、以下の内容を記述します。
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
)
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.Int("age").
Positive(),
field.String("name").
Default("unknown"),
}
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return nil
}
3-3. データベースの準備
スキーマからテーブルを作成するためのDBを準備します。
DBはdocker-composeで準備するので、以下のようにdocker-compose.yml
を作成します。
touch docker-compose.yml
version: "3.8"
services:
postgres_versioned:
image: postgres:16.1-alpine
container_name: postgres_versioned
environment:
POSTGRES_DB: entdemo
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
volumes:
- ./data/db_data/volume:/var/lib/postgresql/data
準備ができたら、コンテナを起動させます。
docker-compose up -d
3-4. マイグレーション
atlasを用いたバージョン管理型のマイグレーションには方法が2つありますが、公式でお勧めされている手法を試したいと思います。
atlas migrate diff
を用いた方法
3-4-1. ターミナルから、atlasを用いてマイグレーションファイルを生成する方法です。
3-4-1-1. マイグレーションファイルの作成
まず、以下のコマンドを実行します。
$ atlas migrate diff add_user_schema \
--dir "file://ent/migrate/migrations" \
--to "ent://ent/schema" \
--dev-url "docker://postgres/16/test?search_path=public"
正常に実行されると、以下の2つのファイルがent/migrate/migrations/
の中に生成されます。
-
{timestamp}_{diffコマンドで指定した名前}.sql
- マイグレーションを行うファイルです。今回、私の環境では
20240212102205_add_user_schema.sql
という名前でした。
- マイグレーションを行うファイルです。今回、私の環境では
-
atlas.sum
- マイグレーションディレクトリの完全性を保証するファイルです。
- マイグレーションの順序や内容が後から変更された場合に、開発者が対処するために利用されます。
3-4-1-2. マイグレーションが完了していないことを確認する
現時点では、マイグレーションは実行されていません。
これを確認するために、atlas migrate status
を実行して確認してみましょう。
$ atlas migrate status \
--dir "file://ent/migrate/migrations" \
--url "postgres://postgres:password@localhost:5432/entdemo_versioned?search_path=public&sslmode=disable"
このコマンドから、以下のことがわかります。
- Migration Statusが
PENDING
なので、実行されていないマイグレーションファイルがあることがわかります。 - Current Versionから、まだ一度もマイグレーションが実行されていないことが確認できます。
- Next Versionから、次に実行される予定のマイグレーションを確認することができます。
- Executed Filesから、過去に実行されたマイグレーションファイルの数がわかります。現時点では、何も実行されていないので0です。
- Pending Filesから、待機中のマイグレーションファイルの数がわかります。今回は
20240212102205_add_user_schema.sql
が控えているので、数が1になっています。
Migration Status: PENDING
-- Current Version: No migration applied yet
-- Next Version: 20240212102205
-- Executed Files: 0
-- Pending Files: 1
3-4-1-3. マイグレーションの実行
それでは、migrationを実行してみましょう。
$ atlas migrate apply \
--dir "file://ent/migrate/migrations" \
--url "postgres://postgres:password@localhost:5432/entdemo_versioned?search_path=public&sslmode=disable"
マイグレーションが完了すると、以下のように出力されます。
Migrating to version 20240212102205 (1 migrations in total):
-- migrating version 20240212102205
-> CREATE TABLE "users" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "age" bigint NOT NULL, "name" character varying NOT NULL DEFAULT 'unknown', PRIMARY KEY ("id"));
-- ok (16.220259ms)
-------------------------
-- 96.437614ms
-- 1 migrations
-- 1 sql statements
3-4-1-4. マイグレーションの完了を確認
もう一度、マイグレーションのステータスを確認してみましょう。
$ atlas migrate status \
--dir "file://ent/migrate/migrations" \
--url "postgres://postgres:password@localhost:5432/entdemo_versioned?search_path=public&sslmode=disable"
以下のようにステータスが更新されていることがわかります。
これで、無事にマイグレーションが完了しました!
Migration Status: OK
-- Current Version: 20240212102205
-- Next Version: Already at latest version
-- Executed Files: 1
-- Pending Files: 0
3-5. マイグレーションのdown
4章のatlas cloudとの連携を行う前に、適応したマイグレーションをdownしておきましょう。
downには、以下のようにatlas migrate donw
コマンドを利用します。
$ atlas migrate down \
--dir "file://ent/migrate/migrations" \
--url "postgres://postgres:password@localhost:5432/entdemo_versioned?search_path=public&sslmode=disable" \
--dev-url "docker://postgres/16/dev?search_path=public" \
ちなみに、--dry-run
オプションを付与すると、実際にdonwは実行されず、以下のように処理の内容を確認することができます。
Migrating down from version 20240212102205 (1 migration in total):
-- checks before reverting version 20240212102205
-> SELECT NOT EXISTS (SELECT 1 FROM "users") AS "is_empty"
-- ok (2.683552ms)
-- reverting version 20240212102205
-> DROP TABLE "users"
-- ok (2.686391ms)
-------------------------
-- 2.688966ms
-- 1 migration
-- 1 sql statement
4. atlas cloudとの連携
最後に、atlas cloudと連携してみましょう!
ここでは、atlas cloudのopenプラン以上のアカウントを持っている前提で話を進めます。
4-1. atlas cloudにmigration ディレクトリをプッシュ
まず、atlas cli上でログインします。
$ atlas login <アカウント名>
次に、ent/migrate/
にcdします。
$ cd ent/migrate
最後に、ent/migrate/
で、atlas migrate push
コマンドを用いて、migrations/
の内容をpushします。
$ atlas migrate push entdemo --dev-url "docker://postgres/15/dev?search_path=public"
無事にpushが完了すると、以下のようにatlas cloud上にentdemoの内容が表示されます。
atlas.hcl
を用いたマイグレーション
4-2. 今回はatlas.hcl
を用いて、atlas cloudと連携しながらマイグレーションを行おうと思うので、以下の内容でatlas.hcl
を作成します。
env "local" {
url = "postgres://postgres:password@localhost:5432/entdemo_versioned?search_path=public&sslmode=disable"
migration {
dir = "atlas://entdemo"
}
}
あとは、以下のコマンドでmigrationを実行して下さい。
$ atlas migrate apply --env local
正常にマイグレーションが実行されると、以下のように出力されます。
Migrating to version 20240212102205 (1 migrations in total):
-- migrating version 20240212102205
-> CREATE TABLE "users" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "age" bigint NOT NULL, "name" character varying NOT NULL DEFAULT 'unknown', PRIMARY KEY ("id"));
-- ok (35.192543ms)
-------------------------
-- 103.639911ms
-- 1 migration
-- 1 sql statement
https://<あなたのアカウント名>.atlasgo.cloud/deployments/<一意の数値>
atlas cloudとの連携も確認してみましょう。
まず、Migrationsタブには、以下のように実行された内容が記録されていきます。
そして、Databasesのタブには、スキーマごとにMigrationの情報が記録されていきます。
5.Github Actionsとatlas cloudの連携
最後に、簡単なworkflowを作成して、Github Actionsとatlas cloudを連携してみましょう!
5-1.Github Actionsの準備
まず、Set Up CIの案内に従って、以下のようにTokenを作成します。
後は表示されている手順に従って、Github CLIを操作するだけです。
atlasの拡張機能をインストールして
gh extension install ariga/gh-atlas
必要な権限スコープを持つ新しい認証トークンを取得し
$ gh auth refresh -s write:packages,workflow
Github actionsのworkflowのPRを作成します。
$ gh atlas init-action --token <あなたのToken>
あとは、作成されたPRをmainブランチにマージするだけです。
5-2. Github Actionsの挙動を確認
それでは、Github Actionsの挙動を確認してみましょう。
まず、ent/schema/user.go
にemailフィールドを追加して、マイグレーションファイルを作成します。
Positive(),
field.String("name").
Default("unknown"),
+ field.String("email").
+ Default("unknown"),
}
}
$ atlas migrate diff \
--dir "file://ent/migrate/migrations" \
--to "ent://ent/schema" \
--dev-url "docker://postgres/16/test?search_path=public"
後は、これらの変更を含んだPRを作成します。
正常に、Github Actionsが動作すると、以下のようにCIが動作するので、問題がなかったらmainブランチにマージをしましょう!
5-3. atlas cloudのCI Runsの確認
atlas cloud上で、どのように表示されているか確認しておきましょう!
まず、今回のPRに関連して、色々とCIが実行されていることがわかります。
CIの内容を確認すると、以下のようにlintが実行され、どのフィールドが追加されたかが一目でわかるようになっています。
まとめ
長らく時間が空いてしまいましたが、今回はatlasを用いたバージョン管理型マイグレーションの紹介を行いました!
atlas + atlas cloudをCI/CDに組み込めば、マイグレーションの自動化も安全に実行できそうな気配を感じます!
現時点では、あまりドキュメントを読み込めていないので、今後も色々手探りで遊んでみながら便利な使い方などを見つけたら、また記事にしてみようと思います。
atlasやatlas cloudの便利な利用方法をご存じの方がいたら、是非コメント欄などで教えてもらえると嬉しいです!
Discussion