create-migration
1
总安装量
1
周安装量
#43611
全站排名
安装命令
npx skills add https://github.com/sjtw/tarkov-build-optimiser --skill create-migration
Agent 安装分布
amp
1
opencode
1
kimi-cli
1
codex
1
github-copilot
1
antigravity
1
Skill 文档
Create Migration Skill
Use this skill when making database schema changes.
Scope
- Adding new tables
- Modifying columns or constraints
- Creating or dropping indexes
- Any DDL operation
Creating a New Migration
Step 1: Generate Migration File
task migrate:create -- your_migration_name
Naming conventions:
- Use snake_case
- Be descriptive but concise
- Use prefixes:
add_,create_,drop_,modify_,update_
Examples:
task migrate:create -- add_weapon_stats_table
task migrate:create -- add_index_on_trader_offers
task migrate:create -- modify_item_properties_column
This creates a timestamped file in migrations/:
migrations/YYYYMMDDHHMMSS_your_migration_name.go
Step 2: Write the Migration
The generated file will have this structure:
package migrations
import (
"database/sql"
"github.com/pressly/goose/v3"
)
func init() {
goose.AddMigrationContext(upYourMigrationName, downYourMigrationName)
}
func upYourMigrationName(ctx context.Context, tx *sql.Tx) error {
// This code is executed when the migration is applied.
return nil
}
func downYourMigrationName(ctx context.Context, tx *sql.Tx) error {
// This code is executed when the migration is rolled back.
return nil
}
In the up function:
- Write SQL to apply the change
- Use
tx.ExecContext(ctx, "SQL HERE")
In the down function:
- Write SQL to reverse the change
- Make it possible to rollback safely
Example:
func upAddWeaponStatsTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
CREATE TABLE weapon_stats (
id SERIAL PRIMARY KEY,
weapon_id VARCHAR(255) NOT NULL,
recoil_vertical INT NOT NULL,
recoil_horizontal INT NOT NULL,
ergonomics INT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_weapon_stats_weapon_id ON weapon_stats(weapon_id);
`)
return err
}
func downAddWeaponStatsTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `DROP TABLE IF EXISTS weapon_stats;`)
return err
}
Step 3: Apply the Migration
# Recommended for DevContainer (assuming database is running)
task migrate:up
# Use if database needs to be started via Docker Compose
task migrate:up:docker
What it does:
migrate:up: Builds the migration binary and runs migrations against the existing database.migrate:up:docker: Ensures PostgreSQL is running via Docker Compose, then applies migrations.
Verify migration applied:
docker compose exec postgres psql -U $POSTGRES_USER -d $POSTGRES_DB -c "\dt"
Step 4: Test the Migration
Test the migration works:
# Apply migration
task migrate:up
# Run integration tests
task test:integration
Test rollback works:
# Rollback the migration
task migrate:down
# Verify database is in previous state
docker compose exec postgres psql -U $POSTGRES_USER -d $POSTGRES_DB -c "\dt"
# Reapply
task migrate:up
Migration Best Practices
DO:
- â Keep migrations small and focused (one logical change per migration)
- â
Provide a
downfunction that reverses the change when feasible - â
Test both
upanddownmigrations before merging - â goose wraps migrations in transactions automatically
- â Add indexes for foreign keys and frequently queried columns
- â
Use
IF NOT EXISTS/IF EXISTSfor safety when appropriate
DON’T:
- â Modify existing migration files after they’re merged (create a new migration instead)
- â Use application code in migrations (keep them SQL-only)
- â Make data changes that can’t be reversed in
down - â Forget to handle the error return value
- â Create huge migrations that change many things at once
Common Migration Patterns
Add a Table
func upCreateTableName(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
CREATE TABLE table_name (
id SERIAL PRIMARY KEY,
field1 VARCHAR(255) NOT NULL,
field2 INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
`)
return err
}
func downCreateTableName(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `DROP TABLE IF EXISTS table_name;`)
return err
}
Add a Column
func upAddColumnToTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
ALTER TABLE table_name
ADD COLUMN new_column VARCHAR(255);
`)
return err
}
func downAddColumnToTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
ALTER TABLE table_name
DROP COLUMN IF EXISTS new_column;
`)
return err
}
Add an Index
func upAddIndexOnTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
CREATE INDEX idx_table_column ON table_name(column_name);
`)
return err
}
func downAddIndexOnTable(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, `
DROP INDEX IF EXISTS idx_table_column;
`)
return err
}
Troubleshooting
Migration fails with “docker”: executable file not found:
- This happens if you try to run
task migrate:up:dockerin an environment without Docker (like a devcontainer). - Use
task migrate:upinstead if your database is already running.
Migration fails to apply:
- Check SQL syntax
- Verify table/column names exist
- Check if migration was already partially applied
- View database logs:
docker compose logs postgres
Can’t rollback migration:
- Check if
downfunction properly reverses theupfunction - Some operations (like dropping columns with data) might need manual intervention
- Consider if rollback is safe with existing data
Migration applied but tests fail:
- Verify the schema change matches your model expectations
- Check if indexes are created correctly
- Ensure foreign key constraints are correct
“goose: no migrations to run” but migration file exists:
- Ensure the file is in
migrations/directory - Check the filename format:
YYYYMMDDHHMMSS_name.go - Verify the file has
package migrationsat the top - Rebuild:
task migrate:build
Viewing Migration Status
# See applied migrations in database
docker compose exec postgres psql -U $POSTGRES_USER -d $POSTGRES_DB -c "SELECT * FROM goose_db_version;"
# See migration files
ls -la migrations/
CI/CD
In CI, migrations run via:
task migrate:ci
This skips the compose:postgres:up dependency (database already running in CI).