migcheck

package
v0.6.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2026 License: MIT Imports: 7 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckDuplicates

func CheckDuplicates(dir string, names []string) diag.List

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

func CheckNames(dir string, names []string, sev diag.Severity) diag.List

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

func CheckOutOfOrder(added []string, base string, baseMax int64) diag.List

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

func MaxVersion(names []string) int64

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.

func Version

func Version(name string) (int64, bool)

Version returns the version goose will give a migration file. The second return is false when the name is not one goose would apply at all.

The argument may be a bare name or a path; only the last element is read.

func WellNamed

func WellNamed(name string) bool

WellNamed reports whether a name is the NNNNN_snake_case.sql form rig requires. A name that is not is still a migration goose applies; see Version.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL