Documentation
¶
Overview ¶
Package migcheck checks a project's migration file names before they are applied to anything.
goose decides two things from a file name alone — which version a migration is, and what order the versions run in — and it reports a problem with either at boot, against a live database, having already applied whatever came before. That is the wrong moment and the wrong machine. Everything here is answerable from the names on disk plus what the base branch already has, so it is answerable in a pull request.
Three rules:
- The name is NNNNN_snake_case.sql (RIG6050). This is rig's convention, not goose's, and it is the one of the three a project may turn off.
- No two files in the directory claim the same version (RIG6051). goose records one version number per applied migration, so a second file with the same number is one that never runs and never will.
- A migration added on this branch is numbered above everything on the base ref (RIG6052). Merged below, it is a migration goose has already stepped past, and it reports it as missing rather than applying it.
Two parses, on purpose ¶
WellNamed demands exactly five digits; Version accepts any number of them. The difference is not laxity. rig's convention is the five-digit form, so 25_late.sql fails RIG6050 — but goose reads that file as version 25 regardless, so it can still collide with 00025_early.sql and still land out of order. A collision check that only looked at well-named files would let the badly-named one through the two rules that describe what actually breaks.
So the naming rule is strict and everything about version numbers is lenient, and a single bad file can earn all three diagnostics. That is the honest count: three separate things are wrong with it.
No I/O ¶
Every check takes the names it is to judge. Reading the directory belongs to the caller, and so does asking git what the base ref has — which is what lets the whole of this be tested without a repository, and what keeps one rule from deciding how another one's files were found.
Index ¶
- func CheckDuplicates(dir string, names []string) diag.List
- func CheckNames(dir string, names []string, sev diag.Severity) diag.List
- func CheckOutOfOrder(added []string, base string, baseMax int64) diag.List
- func MaxVersion(names []string) int64
- func Version(name string) (int64, bool)
- func WellNamed(name string) bool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckDuplicates ¶
CheckDuplicates reports every version number in dir claimed by more than one file.
Padding does not save two files from being the same version: goose parses the prefix as a number, so 00025_a.sql and 25_b.sql are both version 25 and only one of them will ever run. Which one is whichever goose sorted first, and the other is a migration that is in the repository, is not in the database, and says nothing about it.
func CheckNames ¶
CheckNames reports every file in dir whose name is not the form rig requires.
Only files that look like a migration attempt are judged: a README.md beside the migrations is not a badly-named migration, and reporting it would make the rule impossible to leave on. What counts as an attempt is a .sql file, which is the extension goose reads and the only thing in the directory that will be run.
sev is the severity from the project's `validate.migration_filename`. An empty severity reports nothing, which is how the rule is turned off.
func CheckOutOfOrder ¶
CheckOutOfOrder reports every added migration numbered at or below baseMax, the highest version the base ref already has.
At or below, not below: a migration equal to the base's highest is either a duplicate of it or a renumbering of something already applied, and neither is a migration that runs.
baseMax of zero — nothing on the base ref, or no migrations directory there — passes everything, which is the first migration in a new project.
func MaxVersion ¶
MaxVersion is the highest version among names, and zero when none of them is a migration. Zero is a safe floor because goose numbers from one.
Types ¶
This section is empty.