github.com/supabase/cli@v1.168.1/internal/migration/up/up.go (about)

     1  package up
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/go-errors/errors"
    10  	"github.com/jackc/pgconn"
    11  	"github.com/jackc/pgx/v4"
    12  	"github.com/spf13/afero"
    13  	"github.com/supabase/cli/internal/migration/apply"
    14  	"github.com/supabase/cli/internal/migration/list"
    15  	"github.com/supabase/cli/internal/utils"
    16  )
    17  
    18  var (
    19  	errMissingRemote = errors.New("Found local migration files to be inserted before the last migration on remote database.")
    20  	errMissingLocal  = errors.New("Remote migration versions not found in " + utils.MigrationsDir + " directory.")
    21  )
    22  
    23  func Run(ctx context.Context, includeAll bool, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
    24  	conn, err := utils.ConnectByConfig(ctx, config, options...)
    25  	if err != nil {
    26  		return err
    27  	}
    28  	defer conn.Close(context.Background())
    29  	pending, err := GetPendingMigrations(ctx, includeAll, conn, fsys)
    30  	if err != nil {
    31  		return err
    32  	}
    33  	return apply.MigrateUp(ctx, conn, pending, fsys)
    34  }
    35  
    36  func GetPendingMigrations(ctx context.Context, includeAll bool, conn *pgx.Conn, fsys afero.Fs) ([]string, error) {
    37  	remoteMigrations, err := list.LoadRemoteMigrations(ctx, conn)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	localMigrations, err := list.LoadLocalMigrations(fsys)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	// Find unapplied local migrations older than the latest migration on
    46  	// remote, and remote migrations that are missing from local.
    47  	var unapplied, missing []string
    48  	i, j := 0, 0
    49  	for i < len(remoteMigrations) && j < len(localMigrations) {
    50  		remote := remoteMigrations[i]
    51  		filename := localMigrations[j]
    52  		// Check if migration has been applied before, LoadLocalMigrations guarantees a match
    53  		local := utils.MigrateFilePattern.FindStringSubmatch(filename)[1]
    54  		if remote == local {
    55  			j++
    56  			i++
    57  		} else if remote < local {
    58  			missing = append(missing, remote)
    59  			i++
    60  		} else {
    61  			// Include out-of-order local migrations
    62  			unapplied = append(unapplied, filename)
    63  			j++
    64  		}
    65  	}
    66  	// Ensure all remote versions exist on local
    67  	if j == len(localMigrations) {
    68  		missing = append(missing, remoteMigrations[i:]...)
    69  	}
    70  	if len(missing) > 0 {
    71  		utils.CmdSuggestion = suggestRevertHistory(missing)
    72  		return nil, errMissingLocal
    73  	}
    74  	// Enforce migrations are applied in chronological order by default
    75  	if !includeAll && len(unapplied) > 0 {
    76  		utils.CmdSuggestion = suggestIgnoreFlag(unapplied)
    77  		return nil, errMissingRemote
    78  	}
    79  	pending := localMigrations[len(remoteMigrations)+len(unapplied):]
    80  	return append(unapplied, pending...), nil
    81  }
    82  
    83  func suggestRevertHistory(versions []string) string {
    84  	result := fmt.Sprintln("\nMake sure your local git repo is up-to-date. If the error persists, try repairing the migration history table:")
    85  	result += fmt.Sprintln(utils.Bold("supabase migration repair --status reverted " + strings.Join(versions, " ")))
    86  	result += fmt.Sprintln("\nAnd update local migrations to match remote database:")
    87  	result += fmt.Sprintln(utils.Bold("supabase db pull"))
    88  	return result
    89  }
    90  
    91  func suggestIgnoreFlag(filenames []string) string {
    92  	result := "\nRerun the command with --include-all flag to apply these migrations:\n"
    93  	for _, name := range filenames {
    94  		result += fmt.Sprintln(utils.Bold(filepath.Join(utils.MigrationsDir, name)))
    95  	}
    96  	return result
    97  }