2.7 KiB
2.7 KiB
| name | description | user-invocable |
|---|---|---|
| migration | Use when creating or editing files in pkg/migration/. Covers cross-DB type safety across MySQL/PostgreSQL/SQLite, DDL error handling, time-column conventions, and path sanitization. | true |
Database Migrations
Migrations are irreversible in production. Vikunja supports MySQL, PostgreSQL, and SQLite — every migration must work on all three.
Before writing
- Generate the skeleton:
mage dev:make-migration <StructName>. - The migration struct must mirror the model in
pkg/models/exactly (field names, types, xorm tags). - Use
time.Timefor time columns. Never usestring,varchar, ortextfor times. - For renames or type changes, verify the conversion is safe on all three DBs:
- MySQL will silently coerce
VARCHAR→BIGINTduringALTER. Don't rely on that — migrate data explicitly. - SQLite has limited
ALTER TABLE; preferxormmigration helpers over raw SQL when possible. - PostgreSQL is strict about types; explicit casts are often required.
- MySQL will silently coerce
Error handling on DDL
Every error from tx.Exec, session.Exec, or xorm calls must be handled. Silent discards are the most commonly flagged bug in migration reviews.
// WRONG — silently drops errors; migration reports success even on failure
_, _ = tx.Exec("CREATE INDEX idx_foo ON bar(baz)")
// RIGHT — error is returned so the migration rolls back cleanly
if _, err := tx.Exec("CREATE INDEX idx_foo ON bar(baz)"); err != nil {
return err
}
If you must discard a DB error (e.g., idempotent best-effort cleanup where the index might already exist), write a one-line comment explaining why. No comment = reviewer will flag it.
Path and user input
If the migration touches user-supplied paths, filenames, or import blobs (restore, dump, import modules under pkg/modules/migration/), sanitize before use. Never filepath.Join raw input. Watch for .. traversal in archive entry names.
Model and frontend sync
- If the migration adds or changes a field, update the struct in
pkg/models/with matching xorm tags. - Update the TypeScript interface in
frontend/src/modelTypes/to match the Go struct shape. Frontend services must match backend model structure exactly.
Testing
- Migrations don't have dedicated unit tests, but the model's feature tests must pass against the new schema. Run
mage test:feature(uses SQLite by default). - If you suspect DB-specific behavior, flag it in the PR description so reviewers know to verify against MySQL/PostgreSQL.
Related
- Existing examples: browse
pkg/migration/for patterns; recent files are usually the cleanest references. - Never edit
pkg/swagger/(generated). - Never commit
config.yml.sample(generated bymage generate:config-yaml).