Skip to content

Commit

Permalink
feat: new-sql-migration command (#3857)
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas authored Dec 29, 2024
1 parent 13782ad commit 9dc75f5
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 20 deletions.
78 changes: 78 additions & 0 deletions frontend/cli/cmd_new_migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package main

import (
"context"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

"github.com/amacneil/dbmate/v2/pkg/dbmate"

"github.com/block/ftl/internal/log"
"github.com/block/ftl/internal/moduleconfig"
"github.com/block/ftl/internal/watch"
)

type newSQLMigrationCmd struct {
Datasource string `arg:"" help:"The qualified name of the datasource in the form module.datasource to create the migration for. If the module is not specified FTL will attempt to infer it from the current working directory."`
Name string `arg:"" help:"Name of the migration, this will be included in the migration file name."`
}

func (i newSQLMigrationCmd) Run(ctx context.Context) error {

dir, err := os.Getwd()
if err != nil {
return fmt.Errorf("could not get current working directory: %w", err)
}
modules, err := watch.DiscoverModules(ctx, []string{dir})
var module *moduleconfig.UnvalidatedModuleConfig
parts := strings.Split(i.Datasource, ".")
var dsName string
if len(parts) == 1 && len(modules) == 1 {
module = &modules[0]
dsName = parts[0]
} else if len(parts) == 2 {
for i := range modules {
if modules[i].Module == parts[0] {
module = &modules[i]
break
}
}
dsName = parts[1]
} else {
return fmt.Errorf("invalid datasource %q, must be in the form module.datasource", i.Datasource)
}
if module == nil {
return fmt.Errorf("could not find module %q", parts[0])
}

if err != nil {
return fmt.Errorf("could not discover modules: %w", err)
}
migrationDir := module.SQLMigrationDirectory
if migrationDir == "" {
language := module.Language
plugin, err := createLanguagePlugin(ctx, language)
if err != nil {
return fmt.Errorf("could not create plugin for language %q: %w", language, err)
}
defaults, err := plugin.ModuleConfigDefaults(ctx, module.Dir)
if err != nil {
return fmt.Errorf("could not get module config defaults for language %q: %w", language, err)
}
migrationDir = defaults.SQLMigrationDir
}
migrationDir = filepath.Join(module.Dir, migrationDir, dsName)

logger := log.FromContext(ctx)
logger.Debugf("Creating DBMate SQL migration %s in module %q in %s", i.Name, module.Module, migrationDir)
db := dbmate.New(&url.URL{})
db.MigrationsDir = []string{migrationDir}
err = db.NewMigration(i.Name)
if err != nil {
return fmt.Errorf("failed to create migration: %w", err)
}
return nil
}
39 changes: 20 additions & 19 deletions frontend/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,26 @@ type InteractiveCLI struct {
AdminEndpoint *url.URL `help:"Admin endpoint." env:"FTL_ADMIN_ENDPOINT" default:"http://127.0.0.1:8896"`
Trace string `help:"File to write golang runtime/trace output to." hidden:""`

Ping pingCmd `cmd:"" help:"Ping the FTL cluster."`
Status statusCmd `cmd:"" help:"Show FTL status."`
Init initCmd `cmd:"" help:"Initialize a new FTL project."`
Profile profileCmd `cmd:"" help:"Manage profiles."`
New newCmd `cmd:"" help:"Create a new FTL module. See language specific flags with 'ftl new <language> --help'."`
PS psCmd `cmd:"" help:"List deployments."`
Call callCmd `cmd:"" help:"Call an FTL function."`
Bench benchCmd `cmd:"" help:"Benchmark an FTL function."`
Replay replayCmd `cmd:"" help:"Call an FTL function with the same request body as the last invocation."`
Update updateCmd `cmd:"" help:"Update a deployment."`
Kill killCmd `cmd:"" help:"Kill a deployment."`
Schema schemaCmd `cmd:"" help:"FTL schema commands."`
Build buildCmd `cmd:"" help:"Build all modules found in the specified directories."`
Deploy deployCmd `cmd:"" help:"Build and deploy all modules found in the specified directories."`
Download downloadCmd `cmd:"" help:"Download a deployment."`
Secret secretCmd `cmd:"" help:"Manage secrets."`
Config configCmd `cmd:"" help:"Manage configuration."`
Pubsub pubsubCmd `cmd:"" help:"Manage pub/sub."`
Release releaseCmd `cmd:"" help:"Manage releases."`
Ping pingCmd `cmd:"" help:"Ping the FTL cluster."`
Status statusCmd `cmd:"" help:"Show FTL status."`
Init initCmd `cmd:"" help:"Initialize a new FTL project."`
Profile profileCmd `cmd:"" help:"Manage profiles."`
New newCmd `cmd:"" help:"Create a new FTL module. See language specific flags with 'ftl new <language> --help'."`
PS psCmd `cmd:"" help:"List deployments."`
Call callCmd `cmd:"" help:"Call an FTL function."`
Bench benchCmd `cmd:"" help:"Benchmark an FTL function."`
Replay replayCmd `cmd:"" help:"Call an FTL function with the same request body as the last invocation."`
Update updateCmd `cmd:"" help:"Update a deployment."`
Kill killCmd `cmd:"" help:"Kill a deployment."`
Schema schemaCmd `cmd:"" help:"FTL schema commands."`
Build buildCmd `cmd:"" help:"Build all modules found in the specified directories."`
Deploy deployCmd `cmd:"" help:"Build and deploy all modules found in the specified directories."`
Download downloadCmd `cmd:"" help:"Download a deployment."`
Secret secretCmd `cmd:"" help:"Manage secrets."`
Config configCmd `cmd:"" help:"Manage configuration."`
Pubsub pubsubCmd `cmd:"" help:"Manage pub/sub."`
Release releaseCmd `cmd:"" help:"Manage releases."`
NewSQLMigration newSQLMigrationCmd `cmd:"" help:"Create a new SQL Database migration."`
}

type CLI struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public String getValue(String propertyName) {

@Override
public String getName() {
return "Quarkus Static Config Source";
return "FTL Static Config Source";
}
}

0 comments on commit 9dc75f5

Please sign in to comment.