Seeder Tags
Group seeders with tags and run only matching seeders using RunByTag or the CLI --tag flag.
Seeder Tags
New in v1.0.0: Seeder tags, the TaggedSeeder interface, RunByTag(), and the --tag CLI flag are all introduced in v1.0.0.
Tags let you group seeders by purpose — like "development", "testing", or "production" — and run only the seeders that match a specific tag.
The TaggedSeeder Interface
Implement the TaggedSeeder interface to assign tags to a seeder:
type TaggedSeeder interface {
Seeder
Tags() []string
}| Method | Signature | Description |
|---|---|---|
Tags | Tags() []string | Returns the tags this seeder belongs to |
A seeder can have multiple tags. The TaggedSeeder interface extends the base Seeder interface, so you still need to implement Run.
Defining a Tagged Seeder
package seeders
import (
"database/sql"
)
type DevUserSeeder struct{}
func (s *DevUserSeeder) Tags() []string {
return []string{"development", "testing"}
}
func (s *DevUserSeeder) Run(db *sql.DB) error {
_, err := db.Exec(
"INSERT INTO users (name, email) VALUES ($1, $2)",
"Dev User", "dev@example.com",
)
return err
}This seeder runs when either the "development" or "testing" tag is requested.
Running Seeders by Tag
Programmatic API
Use runner.RunByTag() to execute only seeders matching a specific tag:
runner := seeder.NewRunner(db)
runner.Register("DevUserSeeder", &seeders.DevUserSeeder{})
runner.Register("ProdDefaultsSeeder", &seeders.ProdDefaultsSeeder{})
runner.Register("TestFixtureSeeder", &seeders.TestFixtureSeeder{})
// Run only seeders tagged "development"
if err := runner.RunByTag("development"); err != nil {
log.Fatal(err)
}CLI
Use the --tag flag with the db:seed command:
# Run only seeders tagged "development"
go-migration db:seed --tag=development
# Run only seeders tagged "testing"
go-migration db:seed --tag=testingSeeders Without Tags
The TaggedSeeder interface is optional. Seeders that don't implement it:
- Run normally with
runner.RunAll()andrunner.Run() - Are skipped by
runner.RunByTag()— only tagged seeders are considered
// This seeder has no tags — it runs with RunAll() but not RunByTag()
type RoleSeeder struct{}
func (s *RoleSeeder) Run(db *sql.DB) error {
_, err := db.Exec("INSERT INTO roles (name) VALUES ($1)", "admin")
return err
}RunByTag only considers seeders that implement TaggedSeeder. Untagged seeders are silently skipped, not treated as errors.
Complete Example
package main
import (
"database/sql"
"log"
_ "github.com/lib/pq"
"github.com/gopackx/go-migration/seeder"
"your-project/seeders"
)
func main() {
db, err := sql.Open("postgres", "postgres://user:password@localhost:5432/mydb?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
runner := seeder.NewRunner(db)
runner.Register("DevUserSeeder", &seeders.DevUserSeeder{}) // tags: development, testing
runner.Register("ProdDefaultsSeeder", &seeders.ProdDefaultsSeeder{}) // tags: production
runner.Register("RoleSeeder", &seeders.RoleSeeder{}) // no tags
// Run only development seeders
if err := runner.RunByTag("development"); err != nil {
log.Fatal(err)
}
log.Println("Development seeders complete!")
}What's Next?
- Seeder Rollback — undo seeded data with rollback support
- Batch Insert — insert large datasets efficiently