ruangdeveloper.com - Halo-halo! Beberapa waktu yang lalu bekerja dengan project golang yang menggunakan golang-migrate untuk mengelola database migration. Seperti pada umumnya, project ini dikerjakan oleh beberapa developer dengan pembagian tugas yang sudah diatur. Development experience masih terasa menyenangkan hingga tiba saat dimana terjadi kekacauan pada database migration yang kami buat. Jika dituliskan, kira-kira kasusnya seperti ini:
- Developer A membuat migrasi untuk membuat tabel users
- Developer B membuat migrasi untuk mengedit tabel roles
- Developer A dan B open merge request
- Merge request dari developer B diterima, migrasi dijalankan
- Masalah: Merge request dari developer A diterima, migrasi dijalankan tapi tidak tereksekusi karena secara history, migrasi dari developer B lebih terbaru dan golang-migrate menganggap tidak ada migrasi lagi yang perlu dijalankan.
Dari pengalaman itu, saya jadi merindukan kemudahan migrasi database yang dimiliki oleh Laravel, hahaha.
Singkatnya, pengalaman itu menghasilkan sebuah ide untuk membuat database migration tool versi saya sendiri yang menyimpan semua history migrasi seperti yang dilakukan Laravel, dan jadilah Qafoia.
Apa itu Qafoia?
Qafoia adalah sebuah package opensource yang dapat kita gunakan untuk mengelola migrasi database di project golang. Fitur-fitur yang ditawarkan antara lain sebagai berikut:
- Registrasikan migrasi menggunakan go struct, tulis sql script di dalamnya.
- Jalankan migrasi, rollback, refresh, reset dengan mudah.
- Debug SQL script saat migrasi dijalankan.
- Otomatis generate template go struct untuk menulis migrasi.
- Track history migrasi pada tabel khusus yang dapat disesuaikan namanya.
- Saat ini tersedia MySQL dan Postgres driver yang siap digunakan
- Dapat dengan mudah membuat driver versi kamu sendiri.
Penggunaan
Qafoia dirancang agar mudah untuk digunakan tanpa konfigurasi yang terlalu rumit. Kamu dapat mengikuti langkah-langkah berikut.
Install Qafoia
go get -u github.com/ruangdeveloper/qafoia
Inisialisasi Driver
Pada contoh ini kita menggunakan MySqlDriver
yang sudah disediakan.
driver, err := qafoia.NewMySqlDriver(
"localhost",
"3306",
"db username",
"db password",
"db name",
"utf8mb4"
)
Inisialisasi Qafoia
qafoia, err := qafoia.New(&qafoia.Config{
Driver : driver, // driver yang sudah diinisialisasi
MigrationFilesDir : "migrations", // default migrations
MigrationTableName : "migrations", // default migrations
})
Registrasi Migrasi
err := qafoia.Register(
// nanti migration file kita registrasi ke sini
)
Setelah semua diinisialisasi, kita dapat melakukan beberapa operasi dasar migrasi seperti berikut:
List Migration
list, err := q.List(context.Background())
if err != nil {
log.Fatal(err)
}
list.Print()
Contoh output:
+-----------------------------------+-------------+-------------+
| Migration Name | Is Executed | Executed At |
+-----------------------------------+-------------+-------------+
| 20250427064746_create_users_table | false | N/A |
+-----------------------------------+-------------+-------------+
Output akan menyesuaikan dengan migrasi yang kita registrasikan.
Create Migration
err = q.Create("create_users_table")
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 06:47:46 migration file created: migrations/20250427064746_create_users_table.go
Migration file akan disimpan pada direktori yang sudah diatur ketika inisialisasi Qafoia.
Contoh migration file yang dibuat:
package migrations
type M20250427064746CreateUsersTable struct{}
func (m *M20250427064746CreateUsersTable) Name() string {
// Don't change this name
return "20250427064746_create_users_table"
}
func (m *M20250427064746CreateUsersTable) UpScript() string {
// Write your migration SQL here
return ""
}
func (m *M20250427064746CreateUsersTable) DownScript() string {
// Write your rollback SQL here
return ""
}
Kita bisa menuliskan script SQL untuk migrasi dalam fungsi UpScript()
dan menuliskan script SQL untuk rollback dalam fungsi DownScript()
.
Setelah file migrasi dan script SQL dibuat, kita bisa meregistrasikannya seperti berikut:
err := qafoia.Register(
&migrations.M20250427064746CreateUsersTable{},
)
Run Migration
Untuk menjalankan migrasi, kita bisa menggunakan fungsi Migrate()
err = q.Migrate(context.Background())
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 06:56:44 ๐ Applying 1 migration(s)...
2025/04/27 06:56:44 ๐ฆ Migrating: 20250427064746_create_users_table
2025/04/27 06:56:44 โ
Migrated: 20250427064746_create_users_table
Cek ke tabel migrations
di database
name |executed_at |
---------------------------------+-----------------------+
20250427064746_create_users_table|2025-04-27 06:56:44.000|
Rollback Migration
Untuk melakukan rollback, kita bisa menggunakan fungsi Rollback()
. Fungsi ini menerima parameter step yang dapat kita gunakan untuk menentukan akan rollback sampai berapa migrasi.
err = c.qafoia.Rollback(context.Background(), 1)
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 07:02:15 ๐ Rolling back 1 migration(s)...
2025/04/27 07:02:15 ๐ Rolling back: 20250427064746_create_users_table
2025/04/27 07:02:15 โ
Rolled back: 20250427064746_create_users_table
Fresh Migration
Fresh migration akan menghapus semua tabel dalam database lalu menjalankan semua migrasi dari awal. Untuk melakukan fresh migration, kita bisa menggunakan fungsi Fresh()
.
err = c.qafoia.Fresh(context.Background())
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 07:06:33 ๐งน Cleaning database...
2025/04/27 07:06:33 ๐ Running fresh migrations...
2025/04/27 07:06:33 ๐ Applying 1 migration(s)...
2025/04/27 07:06:33 ๐ฆ Migrating: 20250427064746_create_users_table
2025/04/27 07:06:33 โ
Migrated: 20250427064746_create_users_table
2025/04/27 07:06:33 โ
Fresh migration completed successfully
Reset Migration
Reset migration akan menjalankan rollback semua migrasi yang sudah dieksekusi kemudian menjalankan migrasi ulang. Untuk melakukan reset migration, kita bisa menggunakan fungsi Reset()
.
err = c.qafoia.Reset(context.Background())
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 07:09:01 ๐ Resetting 1 executed migration(s)...
2025/04/27 07:09:01 ๐ Rolling back 1 migration(s)...
2025/04/27 07:09:01 ๐ Rolling back: 20250427064746_create_users_table
2025/04/27 07:09:01 โ
Rolled back: 20250427064746_create_users_table
2025/04/27 07:09:01 ๐ Applying 1 migration(s)...
2025/04/27 07:09:01 ๐ฆ Migrating: 20250427064746_create_users_table
2025/04/27 07:09:01 โ
Migrated: 20250427064746_create_users_table
2025/04/27 07:09:01 โ
Migration reset completed successfully
Clean Migration
Clean akan menghapus semua tabel yang ada di database. Untuk melakukan clean migration, kita bisa menggunakan fungsi Clean()
.
err = c.qafoia.Clean(context.Background())
if err != nil {
log.Fatal(err)
}
Contoh output:
2025/04/27 07:10:31 ๐งน Cleaning database...
2025/04/27 07:10:31 โ
Database cleaned successfully
CLI Helper
Qafoia dirancang agar kita bisa menggunakan cara kita sendiri dalam mengeksekusi operasi migrasi. Namun jika kita ingin cara yang cepat, kita bisa memanfaatkan CLI helper yang sudah disediakan. Dengan menggunakan cli helper, kita bisa menjalankan migrasi melalui command line. Beberapa perintah yang tersedia sebagai berikut:
clean
- Clean database (delete all tables)create
- Create a new migrationhelp
- Help about any commandlist
- List all migrationsmigrate
- Run all pending migrations (use –fresh flag for fresh migration)reset
- Rollback all migrations and re-run all migrationsrollback
- Rollback the last migration (use –step flag for setting rollback step)
Untuk menggunakan CLI helper, cukup tambahkan kode berikut:
cli, err := qafoia.NewCli(qafoia.CliConfig{
Qafoia: qafoia, // Qafoia yang sudah diinisialisasi
})
if err != nil {
log.Fatal(err)
}
err = cli.Execute(context.Background())
if err != nil {
log.Fatal(err)
}
Setelah inisialisasi CLI, kita bisa menjalankan perintah seperti berikut:
Menjalankan migrasi
go run main.go migrate
Atau dengan fresh
go run main.go migrate --fresh
Membuat file migrasi
go run main.go create "Create Users Table"
Menampilkan list migrasi
go run main.go list
Rollback migrasi
go run main.go rollback
Atau dengan menentukan step
go run main.go rollback --step 2
Reset migrasi
go run main.go reset
Clean database
go run main.go clean
Contoh File Akhir
File: main.go
package main
import (
"context"
"log"
"test_qafoia_published/migrations"
"github.com/ruangdeveloper/qafoia"
)
func main() {
d, err := qafoia.NewMySqlDriver(
"localhost",
"3306",
"db user",
"db pass",
"db name",
"utf8mb4",
)
if err != nil {
log.Fatal(err)
}
q, err := qafoia.New(&qafoia.Config{
Driver: d,
MigrationFilesDir: "migrations",
MigrationTableName: "migrations",
})
if err != nil {
log.Fatal(err)
}
err = q.Register(
&migrations.M20250427064746CreateUsersTable{},
)
if err != nil {
log.Fatal(err)
}
cli, err := qafoia.NewCli(qafoia.CliConfig{
Qafoia: q,
})
if err != nil {
log.Fatal(err)
}
err = cli.Execute(context.Background())
if err != nil {
log.Fatal(err)
}
}
Kesimpulan
Dari pengalaman menggunakan golang-migrate di proyek Golang, saya menemukan tantangan ketika beberapa developer membuat migrasi dalam waktu berdekatan. Karena golang-migrate hanya mencatat satu versi terakhir yang dijalankan, tidak semua histori migrasi tersimpan. Akibatnya, migrasi bisa saling bertabrakan, urutan migrasi menjadi tidak konsisten, dan potensi error di database pun semakin besar. Dari situ lahir ide untuk membuat sebuah tool baru yang lebih terstruktur, seperti konsep migrasi di Laravel.
Qafoia mengelola migrasi menggunakan struct, mencatat histori di tabel khusus, dan sudah mendukung MySQL serta Postgres. Semua operasi seperti migrate, rollback, fresh, reset, hingga clean database dapat dilakukan dengan perintah yang sederhana. Tersedia juga CLI helper untuk mempermudah penggunaan.
Karena ini adalah proyek open source, saya mengundang teman-teman developer yang tertarik untuk ikut berkontribusi, memberikan masukan, atau membantu mengembangkan Qafoia ke depannya. ๐