From 7130506ba68dee94291844026235aacdb5de94c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9mi=20V=C3=A1nyi?= Date: Fri, 18 Oct 2024 10:55:17 +0200 Subject: [PATCH 1/2] New command: `bootstrap` (#414) This PR adds a new command called `bootstrap`. It runs all the migrations in the specified folder. Migration files are JSON files, ordered alphabetically. Help: ``` > go run . bootstrap -h Bootstrap a new database from a directory of migration files. All files in the directory will be executed in alphabetical order. All migrations are completed. Usage: pgroll bootstrap [flags] Flags: -h, --help help for bootstrap ``` Closes https://github.com/xataio/pgroll/issues/269 --- Makefile | 6 +--- cmd/bootstrap.go | 51 ++++++++++++++++++++++++++++++++ cmd/root.go | 1 + cmd/start.go | 76 ++++++++++++++++++++++++++---------------------- 4 files changed, 94 insertions(+), 40 deletions(-) create mode 100644 cmd/bootstrap.go diff --git a/Makefile b/Makefile index 5b5826de..ceb701c2 100644 --- a/Makefile +++ b/Makefile @@ -20,11 +20,7 @@ lint: examples: @go build @./pgroll init - @for file in examples/*.json; do \ - if [ -f $$file ]; then \ - ./pgroll start --complete $$file; \ - fi \ - done + @./pgroll bootstrap examples @go clean test: diff --git a/cmd/bootstrap.go b/cmd/bootstrap.go new file mode 100644 index 00000000..8666190a --- /dev/null +++ b/cmd/bootstrap.go @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "slices" + + "github.com/spf13/cobra" +) + +var bootstrapCmd = &cobra.Command{ + Use: "bootstrap ", + Short: "Bootstrap a new database from a directory of migration files", + Long: `Bootstrap a new database from a directory of migration files. All files in the directory will be executed +in lexicographical order. All migrations are completed.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + migrationsDir := args[0] + + m, err := NewRoll(cmd.Context()) + if err != nil { + return err + } + defer m.Close() + + // open folder and read all json files + files, err := os.ReadDir(migrationsDir) + if err != nil { + return fmt.Errorf("reading migration directory: %w", err) + } + migrationFiles := []string{} + for _, file := range files { + if file.IsDir() || filepath.Ext(file.Name()) != ".json" { + continue + } + migrationFiles = append(migrationFiles, filepath.Join(migrationsDir, file.Name())) + } + slices.Sort(migrationFiles) + + for _, fileName := range migrationFiles { + if err := runMigrationFromFile(cmd.Context(), m, fileName, true); err != nil { + return fmt.Errorf("running migration file '%s': %w", fileName, err) + } + } + + return nil + }, +} diff --git a/cmd/root.go b/cmd/root.go index 63db7d1d..1b01a1a5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -74,6 +74,7 @@ func Execute() error { rootCmd.AddCommand(analyzeCmd) rootCmd.AddCommand(initCmd) rootCmd.AddCommand(statusCmd) + rootCmd.AddCommand(bootstrapCmd) return rootCmd.Execute() } diff --git a/cmd/start.go b/cmd/start.go index 9e3a142d..6bdba213 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -3,6 +3,7 @@ package cmd import ( + "context" "fmt" "os" "path/filepath" @@ -32,48 +33,53 @@ func startCmd() *cobra.Command { } defer m.Close() - file, err := os.Open(fileName) - if err != nil { - return fmt.Errorf("opening migration file: %w", err) - } - defer file.Close() + return runMigrationFromFile(cmd.Context(), m, fileName, complete) + }, + } - migration, err := migrations.ReadMigration(file) - if err != nil { - return fmt.Errorf("reading migration file: %w", err) - } + startCmd.Flags().BoolVarP(&complete, "complete", "c", false, "Mark the migration as complete") - sp, _ := pterm.DefaultSpinner.WithText("Starting migration...").Start() - cb := func(n int64) { - sp.UpdateText(fmt.Sprintf("%d records complete...", n)) - } + return startCmd +} - err = m.Start(cmd.Context(), migration, cb) - if err != nil { - sp.Fail(fmt.Sprintf("Failed to start migration: %s", err)) - return err - } +func runMigrationFromFile(ctx context.Context, m *roll.Roll, fileName string, complete bool) error { + file, err := os.Open(fileName) + if err != nil { + return fmt.Errorf("opening migration file: %w", err) + } - if complete { - if err = m.Complete(cmd.Context()); err != nil { - sp.Fail(fmt.Sprintf("Failed to complete migration: %s", err)) - return err - } - } + migration, err := migrations.ReadMigration(file) + if err != nil { + file.Close() + return fmt.Errorf("reading migration file: %w", err) + } + file.Close() - version := migration.Name - if version == "" { - version = strings.TrimSuffix(filepath.Base(fileName), filepath.Ext(fileName)) - } - viewName := roll.VersionedSchemaName(flags.Schema(), version) - msg := fmt.Sprintf("New version of the schema available under the postgres %q schema", viewName) - sp.Success(msg) + sp, _ := pterm.DefaultSpinner.WithText("Starting migration...").Start() + cb := func(n int64) { + sp.UpdateText(fmt.Sprintf("%d records complete...", n)) + } - return nil - }, + err = m.Start(ctx, migration, cb) + if err != nil { + sp.Fail(fmt.Sprintf("Failed to start migration: %s", err)) + return err } - startCmd.Flags().BoolVarP(&complete, "complete", "c", false, "Mark the migration as complete") + if complete { + if err = m.Complete(ctx); err != nil { + sp.Fail(fmt.Sprintf("Failed to complete migration: %s", err)) + return err + } + } - return startCmd + version := migration.Name + if version == "" { + version = strings.TrimSuffix(filepath.Base(fileName), filepath.Ext(fileName)) + } + viewName := roll.VersionedSchemaName(flags.Schema(), version) + msg := fmt.Sprintf("New version of the schema available under the postgres %q schema", viewName) + sp.Success(msg) + + return nil } From f628060cc91b68ce614691a45823e69420084f2f Mon Sep 17 00:00:00 2001 From: Ryan Slade Date: Fri, 18 Oct 2024 13:12:40 +0200 Subject: [PATCH 2/2] Explicitly add Postgres 17 checks before merge into main (#415) --- .github/settings.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/settings.yml b/.github/settings.yml index 72c19d66..c4690f9d 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -76,18 +76,22 @@ branches: - test (pg: 14.8, schema: public) - test (pg: 15.3, schema: public) - test (pg: 16.0, schema: public) + - test (pg: 17.0, schema: public) - test (pg: latest, schema: public) - test (pg: 14.8, schema: non_public) - test (pg: 15.3, schema: non_public) - test (pg: 16.0, schema: non_public) + - test (pg: 17.0, schema: non_public) - test (pg: latest, schema: non_public) - examples (pg: 14.8, schema: public) - examples (pg: 15.3, schema: public) - examples (pg: 16.0, schema: public) + - examples (pg: 17.0, schema: public) - examples (pg: latest, schema: public) - examples (pg: 14.8, schema: non_public) - examples (pg: 15.3, schema: non_public) - examples (pg: 16.0, schema: non_public) + - examples (pg: 17.0, schema: non_public) - examples (pg: latest, schema: non_public) - lint