Skip to content

refactor(cli): flat migrations layout + filename-encoded plugin attribution - #33

Merged
dnahilman merged 1 commit into
mainfrom
refactor/flat-migrations
May 26, 2026
Merged

refactor(cli): flat migrations layout + filename-encoded plugin attribution#33
dnahilman merged 1 commit into
mainfrom
refactor/flat-migrations

Conversation

@dnahilman

Copy link
Copy Markdown
Owner

Closes #32.

Summary

Migration files now live in a single flat directory with the plugin name encoded in each filename. This matches the conventions of golang-migrate, goose, atlas, Rails, and Prisma.

Before (nested):

.
├── migrations/20260520120000_initial.up.sql
└── plugins/username/migrations/20260520130000_add_username.up.sql

After (flat):

.
└── migrations/
    ├── 20260520120000_core_initial.up.sql
    └── 20260520130000_username_add_username.up.sql

Breaking change (pre-v1)

  • Source migration files in the repo were renamed to the new convention. Applied-migration tracking is unaffected (tracking table keys on the 14-digit timestamp ID, which is unchanged).
  • migrations.plugins[] in goten.config.yaml is now strictly a list of plugin shorthand names (- username). Explicit-path entries (- ./plugins/username/migrations) are no longer accepted.
  • The legacy nested layout is not auto-detected; existing projects must regenerate their migrations directory via goten init (or rename manually).

What's in the PR

  • R1 Renamed source SQL files: core (*_core_*) + username plugin (*_username_*).
  • R2-R3 discovery.go: walks only cfg.Migrations.CoreDir; parses plugin from filename via regex ^(\d{14})_([a-z][a-z0-9]*)_(.+)\.up\.sql$. Files that don't match the pattern are skipped.
  • R4 init.go: writes both core and plugin SQL files to cfg.Migrations.CoreDir. No more per-plugin destination subdirs.
  • R5 JSON Schema (goten.config.schema.json): migrations.plugins[] items now restricted by regex to lowercase shorthand names.
  • R6-R7 New cmd/goten/scan.go: parses user's *.go files (parser.ImportsOnly), finds imports under github.com/dnahilman/goten/plugins/, warns when those drift from migrations.plugins. Skipped dirs: vendor, .git, .claude, node_modules, testdata. Honors blank imports. Opt out with --no-scan.
  • R8 Tests: updated existing for new filenames, added 6 new scan tests + 1 filename-skip test. Removed resolvePluginEntry and its test (function dropped — no longer needed without path form).
  • R9 examples/basic/goten.config.yaml switched to shorthand. examples/basic/migrations/ is now .gitignored and regenerated by make example via goten init. Integration test (test/adapters/gorm/adapter_test.go) updated to read the renamed core file.
  • R10 CHANGELOG [Unreleased] Breaking-change section + Added section.

Test plan

  • make build — all six modules compile.
  • go test ./internal/... — unit tests pass.
  • cd test && go test ./... — handlers/session/crypto + adapters/gorm/integration + plugins/username all pass with renamed files.
  • cd cmd/goten && go test ./... — 18 tests pass (init + discovery + scan + config).
  • Manual smoke: mktemp -d → echo config with plugins: [username] → goten init --no-scan → confirm 4 files in flat ./migrations/, no ./plugins/ directory created. Output:
    core:        2 written, 0 skipped, 0 overwrote
    username:    2 written, 0 skipped, 0 overwrote
    
  • Reviewer: spot-check that the integration test still finds the renamed core SQL at test/adapters/gorm/adapter_test.go:32.

Follow-up

Wiki Quick Start §5 diagram update is the last step of #32 and will land as a wiki commit immediately after this PR merges.

🤖 Generated with Claude Code

…bution

Closes #32.

Breaking change (pre-v1) — migration files now live in a single flat
directory with the plugin name encoded in each filename:

  20260520120000_core_initial.up.sql
  20260520130000_username_add_username.up.sql

This matches the conventions of golang-migrate, goose, atlas, Rails,
and Prisma. The previous nested per-plugin layout
(./plugins/<name>/migrations/) is no longer supported.

Steps from #32:
- R1 Rename source migration files (core + username) to <ts>_<plugin>_<name>
- R2-R3 discovery.go walks only core_dir, parses plugin from filename
       via regex `^(\d{14})_([a-z][a-z0-9]*)_(.+)\.up\.sql$`
- R4 init.go writes all files (core + plugins) to cfg.Migrations.CoreDir
- R5 JSON Schema: migrations.plugins[] is now strictly shorthand names
- R6-R7 New scan.go: walks user's *.go files for plugin imports,
       warns when those drift from migrations.plugins. --no-scan opts out.
- R8 Tests updated for new filenames; new scan tests added; resolvePluginEntry
     test removed (function dropped — no longer needed without path form)
- R9 examples/basic config switched to shorthand; ./migrations/ regenerated
     by `make example` via `goten init`; gitignored
- R10 CHANGELOG breaking-change section

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dnahilman
dnahilman merged commit 97cda11 into main May 26, 2026
2 checks passed
@dnahilman
dnahilman deleted the refactor/flat-migrations branch May 26, 2026 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(cli): flat migrations/ layout + filename-encoded plugin attribution + import-scan validator

1 participant