Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ignite/cmd/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ with an "--ibc" flag. Note that the default module is not IBC-enabled.
NewScaffoldTypeList(),
NewScaffoldChain(),
NewScaffoldModule(),
NewScaffoldMigration(),
NewScaffoldList(),
NewScaffoldMap(),
NewScaffoldSingle(),
Expand Down
78 changes: 78 additions & 0 deletions ignite/cmd/scaffold_migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ignitecmd

import (
"github.com/spf13/cobra"

"github.com/ignite/cli/v29/ignite/pkg/cache"
"github.com/ignite/cli/v29/ignite/pkg/cliui"
"github.com/ignite/cli/v29/ignite/pkg/xgenny"
"github.com/ignite/cli/v29/ignite/services/scaffolder"
)

// NewScaffoldMigration returns the command to scaffold a module migration.
func NewScaffoldMigration() *cobra.Command {
c := &cobra.Command{
Use: "migration [module] [name]",
Short: "Module migration boilerplate",
Long: `Scaffold no-op migration boilerplate for an existing Cosmos SDK module.

This command creates a new migration file in "x/<module>/migrations/vN/",
increments the module consensus version, and registers the new migration handler
inside "x/<module>/module/module.go".`,
Args: cobra.ExactArgs(2),
PreRunE: migrationPreRunHandler,
RunE: scaffoldMigrationHandler,
}

flagSetPath(c)
c.Flags().AddFlagSet(flagSetYes())

return c
}

func scaffoldMigrationHandler(cmd *cobra.Command, args []string) error {
var (
moduleName = args[0]
migrationName = args[1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need to specify a migration name, this is effectively duplicate, the consensus version is the name. Basically what matter is the module name only.
Then we should be able to simply bump the ConsensusVersion and get the migrationVersion/consensusVersion that way (for the folder name)

appPath = flagGetPath(cmd)
)

session := cliui.New(
cliui.StartSpinnerWithText(statusScaffolding),
cliui.WithoutUserInteraction(getYes(cmd)),
)
defer session.End()

cfg, _, err := getChainConfig(cmd)
if err != nil {
return err
}

sc, err := scaffolder.New(cmd.Context(), appPath, cfg.Build.Proto.Path)
if err != nil {
return err
}

if err := sc.CreateModuleMigration(moduleName, migrationName); err != nil {
return err
}

sm, err := sc.ApplyModifications(xgenny.ApplyPreRun(scaffolder.AskOverwriteFiles(session)))
if err != nil {
return err
}

if err := sc.PostScaffold(cmd.Context(), cache.Storage{}, true); err != nil {
return err
}

modificationsStr, err := sm.String()
if err != nil {
return err
}

session.Println(modificationsStr)
session.Printf("\n🎉 Migration %s added to module %s.\n\n", migrationName, moduleName)

return nil
}
68 changes: 68 additions & 0 deletions ignite/services/scaffolder/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package scaffolder

import (
"os"
"path/filepath"

"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/multiformatname"
modulemigration "github.com/ignite/cli/v29/ignite/templates/module/migration"
)

// CreateModuleMigration scaffolds a new module migration inside an existing module.
func (s Scaffolder) CreateModuleMigration(moduleName, migrationName string) error {
mfModuleName, err := multiformatname.NewName(moduleName, multiformatname.NoNumber)
if err != nil {
return err
}
moduleName = mfModuleName.LowerCase

mfMigrationName, err := multiformatname.NewName(migrationName)
if err != nil {
return err
}
if err := checkGoReservedWord(mfMigrationName.LowerCamel); err != nil {
return errors.Errorf("%s can't be used as a migration name: %w", migrationName, err)
}

ok, err := moduleExists(s.appPath, moduleName)
if err != nil {
return err
}
if !ok {
return errors.Errorf("the module %s doesn't exist", moduleName)
}

moduleFilePath := filepath.Join(s.appPath, moduleDir, moduleName, modulePkg, "module.go")
content, err := os.ReadFile(moduleFilePath)
if err != nil {
return err
}

fromVersion, err := modulemigration.ConsensusVersion(string(content))
if err != nil {
return err
}

opts := &modulemigration.Options{
ModuleName: moduleName,
ModulePath: s.modpath.RawPath,
MigrationName: mfMigrationName,
FromVersion: fromVersion,
ToVersion: fromVersion + 1,
}

versionDir := filepath.Join(s.appPath, opts.MigrationDir())
if _, err := os.Stat(versionDir); err == nil {
return errors.Errorf("migration version %s already exists for module %s", opts.MigrationVersion(), moduleName)
} else if !os.IsNotExist(err) {
return err
}

g, err := modulemigration.NewGenerator(opts)
if err != nil {
return err
}

return s.Run(g)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package <%= migrationVersion %>

import sdk "github.com/cosmos/cosmos-sdk/types"

// <%= migrationFunc %> performs in-place store migrations from version <%= fromVersion %> to <%= toVersion %>.
func <%= migrationFunc %>(_ sdk.Context) error {
return nil
}
40 changes: 40 additions & 0 deletions ignite/templates/module/migration/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package modulemigration

import (
"io/fs"

"github.com/gobuffalo/genny/v2"
"github.com/gobuffalo/plush/v4"

"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/xgenny"
)

// NewGenerator returns the generator to scaffold a new module migration.
func NewGenerator(opts *Options) (*genny.Generator, error) {
subFS, err := fs.Sub(files, "files")
if err != nil {
return nil, errors.Errorf("fail to generate sub: %w", err)
}

g := genny.New()
if err := g.OnlyFS(subFS, nil, nil); err != nil {
return g, err
}

ctx := plush.NewContext()
ctx.Set("fromVersion", opts.FromVersion)
ctx.Set("migrationFunc", opts.MigrationFunc())
ctx.Set("migrationName", opts.MigrationName)
ctx.Set("migrationVersion", opts.MigrationVersion())
ctx.Set("moduleName", opts.ModuleName)
ctx.Set("toVersion", opts.ToVersion)

g.Transformer(xgenny.Transformer(ctx))
g.Transformer(genny.Replace("{{migrationName}}", opts.MigrationName.Snake))
g.Transformer(genny.Replace("{{migrationVersion}}", opts.MigrationVersion()))
g.Transformer(genny.Replace("{{moduleName}}", opts.ModuleName))
g.RunFn(moduleModify(opts))

return g, nil
}
Loading
Loading