fix: allow inlined migration functions in goose validate - #1110
Open
dylanpulver wants to merge 1 commit into
Open
fix: allow inlined migration functions in goose validate#1110dylanpulver wants to merge 1 commit into
dylanpulver wants to merge 1 commit into
Conversation
The Go migration parser asserted that both arguments to AddMigration and friends were *ast.Ident, so an inlined func literal made goose validate fail with "failed to assert argument identifier". The parser only needs to know whether each argument is nil, so it now checks for the nil identifier instead of requiring a named function. Fixes pressly#519
mfridman
reviewed
Sep 1, 2026
|
|
||
| // isNilIdent reports whether the expression is the nil identifier. | ||
| func isNilIdent(expr ast.Expr) bool { | ||
| ident, ok := expr.(*ast.Ident) |
Collaborator
There was a problem hiding this comment.
I think we want to unwrap parentheses here? (nil) is valid Go, but currently gets counted as a migration function.
Using ast.Unparen(expr) before the type assertion should handle.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
goose validaterefuses any Go migration that registers an inlined function:parseInitFuncininternal/migrationstats/migration_go.goasserted that each argument toAddMigrationand its three siblings was an*ast.Identso it could read the function's name. A function literal parses as*ast.FuncLit, the assertion fails, and the whole command aborts. The same rejection hits a function reached through another package, such asgoose.AddMigration(migrations.Up001, migrations.Down001), which parses as*ast.SelectorExpr.The migrations themselves run fine, so the command reports a problem that does not exist.
Why dropping the identifier requirement is safe. The extracted names were never used as names. They were read in exactly two places:
migrationstats.gopassed them tonilAsNumber, which compared the string against"nil"and returned 0 or 1 forStats.UpCount/DownCount— the name itself never reaches the output, since the Name column prints the file name — andparseInitFuncitself, which rejected an empty string as a sign its own parsing had gone wrong. So the name collapsed to a single bit before use, andmigrationstatsis underinternal/, so there is no external caller either. Replacing the two string fields with two booleans set by a nil check preserves every observable output, which is what @mfridman suggested in the issue.The removed branch also formatted
%Tagainstarg, the result of the failed type assertion, rather than againstexpr.argis a nil*ast.Identin that branch, so the message always claimed the argument was an*ast.Identno matter what it really was — that is why #519 showsgot *ast.Identfor a function literal.TestParsingGoMigrationsgains inlined literals for all four register functions, plus mixed cases and a case using qualified names from another package; the existing named-function andnilrows are converted to assert the new booleans.TestGoMigrationStatsInlineruns the inlined sources throughGatherStatsand checks the Up and Down counts thatgoose validateprints.TestParsingGoMigrationsErrorgains a case for a call with the wrong number of arguments.I also built the CLI on both sides of the change and ran
goose validate -vagainst a directory holding the snippet from the issue. Before, it exits 1 with the parse error. After, it prints the row with Up 1 and Down 0.Ran locally:
go test ./internal/migrationstats/...with-race, the package tests for the rest of the module,go test ./tests/gomigrations/...,go vet ./..., andgolangci-lint run ./..., all green. I did not run the Docker-backed integration tests underinternal/testing/integrationorpkg/dockermanage, since Docker was not available here.Fixes #519