diff --git a/evolve/CHANGELOG.md b/evolve/CHANGELOG.md index 0653ae88..f596fc77 100644 --- a/evolve/CHANGELOG.md +++ b/evolve/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## [`v0.5.0`](https://github.com/ignite/apps/releases/tag/evolve/v0.5.0) + +- [#237](https://github.com/ignite/apps/pull/237) Remove `--start` and `--migrate` flags from `evolve add` command. Split into `evolve add` and `evolve add-migrate` commands. +- [#237](https://github.com/ignite/apps/pull/237) Bump dependencies. - [#236](https://github.com/ignite/apps/pull/236) Add `--start` flag to `evolve add` command to optionally disable addition of the start command. ## [`v0.4.3`](https://github.com/ignite/apps/releases/tag/evolve/v0.4.3) diff --git a/evolve/README.md b/evolve/README.md index f0dc2b15..e4cc89af 100644 --- a/evolve/README.md +++ b/evolve/README.md @@ -4,8 +4,8 @@ This Ignite App is aimed to extend [Ignite CLI](https://github.com/ignite/cli) a ## Prerequisites -* Ignite CLI version v28.9.0 or greater. -* Knowledge of blockchain development (Cosmos SDK). +- Ignite CLI version v28.9.0 or greater. +- Knowledge of blockchain development (Cosmos SDK). ## Usage @@ -15,7 +15,7 @@ cd gm ignite app install -g github.com/ignite/apps/evolve@latest ignite evolve add ignite chain build --skip-proto -ignite evolve init +ignite evolve init # only for genesis chains. Otherwise follow the migration steps. ``` Then start `local-da` or use Celestia mainnet as data availability layer. @@ -31,7 +31,25 @@ Finally, run the network: gmd start --rollkit.node.aggregator ``` +### Migrations + +If you want to migrate your running chain to Evolve, first scaffold the migrations commands on your CometBFT chain: + +```sh +ignite evolve add-migrate +``` + +This will add the migration module to your chain. Then add manually a chain migration in the upgrade handler to add this new module and submit a gov proposal to initiate the validator set migration. + +Once the chain has halted, run the migration command on each node: + +```sh +gmd evolve-migrate +``` + +You are ready to integrate Evolve! Follow the [1](#Usage) steps to add it to your chain. + Learn more about Evolve and Ignite in their respective documentation: -* -* +- +- diff --git a/evolve/cmd/add.go b/evolve/cmd/add.go index 832c0859..3e69cee7 100644 --- a/evolve/cmd/add.go +++ b/evolve/cmd/add.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "errors" "path/filepath" "github.com/ignite/cli/v29/ignite/pkg/cliui" @@ -17,9 +16,7 @@ import ( const ( statusScaffolding = "Scaffolding..." - flagPath = "path" - flagStart = "start" - flagMigrate = "migrate" + flagPath = "path" ) func AddHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { @@ -33,16 +30,6 @@ func AddHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { return err } - withStartCmd, err := flags.GetBool(flagStart) - if err != nil { - return err - } - - migrateCometBFT, err := flags.GetBool(flagMigrate) - if err != nil { - return err - } - absPath, err := filepath.Abs(appPath) if err != nil { return err @@ -53,12 +40,9 @@ func AddHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { return err } - binaryName, err := c.Binary() - if err != nil { - return err - } - - g, err := template.NewEvolveGenerator(c, migrateCometBFT, withStartCmd) + g, err := template.NewEvolveGenerator(c, template.GeneratorOptions{ + WithStart: true, + }) if err != nil { return err } @@ -72,16 +56,7 @@ func AddHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { return err } - err = session.Printf("🎉 Evolve (ev-abci) added (`%[1]v`).\n", c.AppPath(), c.Name()) - - if migrateCometBFT { - err = errors.Join(session.Printf("\n")) - err = errors.Join(err, session.Println("Additionally, evolve migration commands and modules successfully scaffolded!")) - err = errors.Join(err, session.Printf("If %s is already live, check out the newly added evolve manager to prepare the chain for migration\n", c.Name())) - err = errors.Join(err, session.Printf("Run `%s evolve-migrate` to migrate CometBFT state to the evolve state.\n", binaryName)) - } - - return err + return session.Printf("🎉 Evolve (ev-abci) added (`%[1]v`).\n", c.AppPath()) } // finish finalize the scaffolded code (formating, dependencies). diff --git a/evolve/cmd/cmd.go b/evolve/cmd/cmd.go index 9449aba6..27411180 100644 --- a/evolve/cmd/cmd.go +++ b/evolve/cmd/cmd.go @@ -23,22 +23,24 @@ func GetCommands() []*plugin.Command { Shorthand: "p", Type: plugin.FlagTypeString, }, + }, + }, + { + Use: "add-migrate", + Short: "Add evolve migration support", + Long: "Add evolve migration helpers and modules for migrating from CometBFT", + Flags: []*plugin.Flag{ { - Name: flagStart, - Usage: "modify start command to use ev-abci (set to false to only add migrate command)", - Type: plugin.FlagTypeBool, - DefaultValue: "true", - }, - { - Name: flagMigrate, - Usage: "scaffolds the migrations helpers and modules (to use when migrating from CometBFT)", - Type: plugin.FlagTypeBool, + Name: flagPath, + Usage: "path of the app", + Shorthand: "p", + Type: plugin.FlagTypeString, }, }, }, { Use: "init", - Short: "Init ev-abci support", + Short: "Init evolve support", Long: "Initialize the chain and a ev-node sequencer via ev-abci.", Flags: []*plugin.Flag{ { diff --git a/evolve/cmd/migrate.go b/evolve/cmd/migrate.go new file mode 100644 index 00000000..952354ec --- /dev/null +++ b/evolve/cmd/migrate.go @@ -0,0 +1,64 @@ +package cmd + +import ( + "context" + "errors" + "path/filepath" + + "github.com/ignite/cli/v29/ignite/pkg/cliui" + "github.com/ignite/cli/v29/ignite/pkg/xgenny" + "github.com/ignite/cli/v29/ignite/services/chain" + "github.com/ignite/cli/v29/ignite/services/plugin" + + "github.com/ignite/apps/evolve/template" +) + +func MigrateHandler(ctx context.Context, cmd *plugin.ExecutedCommand) error { + flags := plugin.Flags(cmd.Flags) + + session := cliui.New(cliui.StartSpinnerWithText(statusScaffolding)) + defer session.End() + + appPath, err := flags.GetString(flagPath) + if err != nil { + return err + } + + absPath, err := filepath.Abs(appPath) + if err != nil { + return err + } + + c, err := chain.New(absPath, chain.CollectEvents(session.EventBus())) + if err != nil { + return err + } + + binaryName, err := c.Binary() + if err != nil { + return err + } + + g, err := template.NewEvolveGenerator(c, template.GeneratorOptions{ + WithMigration: true, + }) + if err != nil { + return err + } + + _, err = xgenny.NewRunner(ctx, appPath).RunAndApply(g) + if err != nil { + return err + } + + if finish(ctx, session, c.AppPath()) != nil { + return err + } + + err = session.Printf("🎉 Evolve migration support added (`%[1]v`).\n", c.AppPath()) + err = errors.Join(err, session.Println("Evolve migration command and module successfully scaffolded!")) + err = errors.Join(err, session.Println("Check out the newly added evolve manager to prepare the chain for migration.")) + err = errors.Join(err, session.Printf("Once the app state is migrated, run `%s evolve-migrate` to migrate CometBFT state to the Evolve state.\n", binaryName)) + + return err +} diff --git a/evolve/go.mod b/evolve/go.mod index 21926859..dce7ab03 100644 --- a/evolve/go.mod +++ b/evolve/go.mod @@ -5,12 +5,12 @@ go 1.24.1 require ( cosmossdk.io/math v1.5.3 github.com/cometbft/cometbft v0.38.17 - github.com/cosmos/cosmos-sdk v0.53.3 + github.com/cosmos/cosmos-sdk v0.53.4 github.com/evstack/ev-node v1.0.0-beta.2.0.20250908090838-0584153217ed github.com/gobuffalo/genny/v2 v2.1.0 github.com/gobuffalo/plush/v4 v4.1.22 github.com/hashicorp/go-plugin v1.6.3 - github.com/ignite/cli/v29 v29.4.0 + github.com/ignite/cli/v29 v29.6.0 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.10.0 ) @@ -210,7 +210,7 @@ require ( github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.12.0 // indirect - github.com/spf13/cast v1.8.0 // indirect + github.com/spf13/cast v1.9.2 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.7 // indirect github.com/subosito/gotenv v1.6.0 // indirect @@ -227,6 +227,7 @@ require ( go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/arch v0.17.0 // indirect golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 // indirect @@ -248,5 +249,5 @@ require ( lukechampine.com/blake3 v1.4.1 // indirect nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.2.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/evolve/go.sum b/evolve/go.sum index 3ed0587e..943a19b6 100644 --- a/evolve/go.sum +++ b/evolve/go.sum @@ -172,8 +172,8 @@ github.com/cosmos/cosmos-db v1.1.1 h1:FezFSU37AlBC8S98NlSagL76oqBRWq/prTPvFcEJNC github.com/cosmos/cosmos-db v1.1.1/go.mod h1:AghjcIPqdhSLP/2Z0yha5xPH3nLnskz81pBx3tcVSAw= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.3 h1:GbDJNUP9OD0gGDVnjecZVZr0ZReD1BtIIxmtgrAsWiw= -github.com/cosmos/cosmos-sdk v0.53.3/go.mod h1:90S054hIbadFB1MlXVZVC5w0QbKfd1P4b79zT+vvJxw= +github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= +github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -422,7 +422,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE= @@ -514,8 +513,8 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ignite/cli/v29 v29.4.0 h1:6ieiEknAXRDUfaAkdGxErPnlS3xRcQE9QxhnrYNvHqk= -github.com/ignite/cli/v29 v29.4.0/go.mod h1:dICC6a96N8eYxqwgar3buBduNlA4e+AVs4vH6IJltL8= +github.com/ignite/cli/v29 v29.6.0 h1:+HaYMD1unqfIo4NbHzwVCnwf9ovYCsPVlo+hS2XLolQ= +github.com/ignite/cli/v29 v29.6.0/go.mod h1:YCMxU6oBvOgb+SehwksJknNwOEj5wN7CFm7V10RU9/M= github.com/ignite/web v1.0.8 h1:St3L6UJj70+h16+No5em8Vn2Hx93tS2G1MyWO/Kt1cc= github.com/ignite/web v1.0.8/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -839,8 +838,8 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= -github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk= -github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= +github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= @@ -945,6 +944,10 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1236,6 +1239,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/evolve/integration/app_test.go b/evolve/integration/app_test.go index a5046333..b3d36862 100644 --- a/evolve/integration/app_test.go +++ b/evolve/integration/app_test.go @@ -49,6 +49,17 @@ func TestEvolve(t *testing.T) { )), )) + env.Must(env.Exec("run evolve add-migrate", + step.NewSteps(step.New( + step.Exec( + envtest.IgniteApp, + "evolve", + "add-migrate", + ), + step.Workdir(app.SourcePath()), + )), + )) + buf := &bytes.Buffer{} bin := path.Join(goenv.Bin(), app.Binary()) env.Must(env.Exec("check evolved", step.NewSteps( diff --git a/evolve/main.go b/evolve/main.go index 0dd40c24..d6cd87a1 100644 --- a/evolve/main.go +++ b/evolve/main.go @@ -32,6 +32,8 @@ func (app) Execute(ctx context.Context, c *plugin.ExecutedCommand, _ plugin.Clie switch args[0] { case "add": return cmd.AddHandler(ctx, c) + case "add-migrate": + return cmd.MigrateHandler(ctx, c) case "init": return cmd.InitHandler(ctx, c) case "edit-genesis": diff --git a/evolve/template/constants.go b/evolve/template/constants.go index 53ddfe0f..f94a8100 100644 --- a/evolve/template/constants.go +++ b/evolve/template/constants.go @@ -10,10 +10,10 @@ const ( const ( EvABCIPackage = "github.com/evstack/ev-abci" - EvABCIVersion = "v1.0.0-beta.2" + EvABCIVersion = "v1.0.0-beta.3" EvNodePackage = "github.com/evstack/ev-node" - EvNodeVersion = "v1.0.0-beta.5" + EvNodeVersion = "v1.0.0-beta.7" GoHeaderPackageFork = "github.com/julienrbrt/go-header" GoHeaderVersionFork = "v0.0.0-20250909151551-cb11b091bf58" diff --git a/evolve/template/generator.go b/evolve/template/generator.go index 6e449037..577c116e 100644 --- a/evolve/template/generator.go +++ b/evolve/template/generator.go @@ -1,17 +1,27 @@ package template import ( + "os" + "path/filepath" + "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/gomodule" "github.com/ignite/cli/v29/ignite/pkg/xgenny" "github.com/ignite/cli/v29/ignite/services/chain" "github.com/ignite/cli/v29/ignite/templates/field/plushhelpers" ) -// NewEvolveGenerator returns the generator to scaffold a evolve integration inside an app. -func NewEvolveGenerator(chain *chain.Chain, withCometMigration, withStartCmd bool) (*genny.Generator, error) { +// GeneratorOptions represents the options for the generator. +type GeneratorOptions struct { + WithStart bool + WithMigration bool +} + +// NewEvolveGenerator returns the generator to scaffold evolve integration. +func NewEvolveGenerator(chain *chain.Chain, opts GeneratorOptions) (*genny.Generator, error) { g := genny.New() ctx := plush.NewContext() plushhelpers.ExtendPlushContext(ctx) @@ -28,15 +38,45 @@ func NewEvolveGenerator(chain *chain.Chain, withCometMigration, withStartCmd boo return nil, errors.Errorf("failed to update go.mod: %w", err) } - if withStartCmd { + g.RunFn(appModify(appPath, opts.WithMigration)) + + if opts.WithStart { g.RunFn(commandsStartModify(appPath, binaryName, chain.Version)) g.RunFn(commandsGenesisInitModify(appPath, binaryName)) g.RunFn(commandsRollbackModify(appPath, binaryName)) } - g.RunFn(commandsMigrateModify(appPath, binaryName)) - if withCometMigration { - g.RunFn(migrateFromCometModify(appPath)) + + if opts.WithMigration { + g.RunFn(commandsMigrateModify(appPath, binaryName)) } return g, nil } + +// updateDependencies makes sure the correct dependencies are added to the go.mod files. +// ev-abci expects evolve v1 to be used. +func updateDependencies(appPath string) error { + gomod, err := gomodule.ParseAt(appPath) + if err != nil { + return errors.Errorf("failed to parse go.mod: %w", err) + } + + gomod.AddNewRequire(EvABCIPackage, EvABCIVersion, false) + gomod.AddNewRequire(EvNodePackage, EvNodeVersion, false) + + // add local-da as go tool dependency (useful for local development) + if err := gomod.AddTool(EvNodeDaCmd); err != nil { + return errors.Errorf("failed to add local-da tool: %w", err) + } + + // add required replaces + gomod.AddReplace(GoHeaderPackage, "", GoHeaderPackageFork, GoHeaderVersionFork) + + // save go.mod + data, err := gomod.Format() + if err != nil { + return errors.Errorf("failed to format go.mod: %w", err) + } + + return os.WriteFile(filepath.Join(appPath, "go.mod"), data, 0o644) +} diff --git a/evolve/template/init.go b/evolve/template/init.go index f412bb0c..444449b1 100644 --- a/evolve/template/init.go +++ b/evolve/template/init.go @@ -1,21 +1,22 @@ package template import ( - "os" + "fmt" "path/filepath" "strings" "github.com/gobuffalo/genny/v2" "github.com/ignite/cli/v29/ignite/pkg/cosmosver" "github.com/ignite/cli/v29/ignite/pkg/errors" - "github.com/ignite/cli/v29/ignite/pkg/gomodule" + "github.com/ignite/cli/v29/ignite/pkg/placeholder" "github.com/ignite/cli/v29/ignite/pkg/xast" + "github.com/ignite/cli/v29/ignite/templates/module" ) // commandsStartModify modifies the application start to use evolve. func commandsStartModify(appPath, binaryName string, version cosmosver.Version) genny.RunFn { return func(r *genny.Runner) error { - cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") + cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd", "commands.go") f, err := r.Disk.Find(cmdPath) if err != nil { return err @@ -75,7 +76,7 @@ func commandsStartModify(appPath, binaryName string, version cosmosver.Version) // this is only needed when the start command is also modified. func commandsGenesisInitModify(appPath, binaryName string) genny.RunFn { return func(r *genny.Runner) error { - cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") + cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd", "commands.go") f, err := r.Disk.Find(cmdPath) if err != nil { return err @@ -122,42 +123,10 @@ func commandsGenesisInitModify(appPath, binaryName string) genny.RunFn { } } -// commandsMigrateModify adds the evolve migrate command to the application. -func commandsMigrateModify(appPath, binaryName string) genny.RunFn { - return func(r *genny.Runner) error { - cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") - f, err := r.Disk.Find(cmdPath) - if err != nil { - return err - } - - content, err := xast.AppendImports( - f.String(), - xast.WithNamedImport("abciserver", "github.com/evstack/ev-abci/server"), - ) - if err != nil { - return err - } - - // add migrate command - alreadyAdded := false // to avoid adding the migrate command multiple times as there are multiple calls to `rootCmd.AddCommand` - content, err = xast.ModifyCaller(content, "rootCmd.AddCommand", func(args []string) ([]string, error) { - if !alreadyAdded { - args = append(args, evolveV1MigrateCmd) - alreadyAdded = true - } - - return args, nil - }) - - return r.File(genny.NewFileS(cmdPath, content)) - } -} - // commandsRollbackModify modifies the application rollback command to use evolve. func commandsRollbackModify(appPath, binaryName string) genny.RunFn { return func(r *genny.Runner) error { - cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd/commands.go") + cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd", "commands.go") f, err := r.Disk.Find(cmdPath) if err != nil { return err @@ -183,32 +152,112 @@ func commandsRollbackModify(appPath, binaryName string) genny.RunFn { } } -// updateDependencies makes sure the correct dependencies are added to the go.mod files. -// ev-abci expects evolve v1 to be used. -func updateDependencies(appPath string) error { - gomod, err := gomodule.ParseAt(appPath) - if err != nil { - return errors.Errorf("failed to parse go.mod: %w", err) +// appModify modifies the app to add the blanked staking module and optionally the migration utilities. +func appModify(appPath string, withMigration bool) genny.RunFn { + replacer := placeholder.New() + + appConfigModify := func(r *genny.Runner, withMigration bool) error { + configPath := filepath.Join(appPath, module.PathAppConfigGo) + f, err := r.Disk.Find(configPath) + if err != nil { + return err + } + + content := f.String() + + if withMigration { + // Import migrationmngr module + content, err = xast.AppendImports(content, + xast.WithNamedImport("migrationmngrmodule", "github.com/evstack/ev-abci/modules/migrationmngr/module"), + xast.WithNamedImport("migrationmngrtypes", "github.com/evstack/ev-abci/modules/migrationmngr/types"), + xast.WithNamedImport("_", "github.com/evstack/ev-abci/modules/migrationmngr"), + ) + if err != nil { + return err + } + + // add migrationmngr module config for depinject + moduleConfigTemplate := `{ + Name: migrationmngrtypes.ModuleName, + Config: appconfig.WrapAny(&migrationmngrmodule.Module{}), + }, + %[1]v` + moduleConfigReplacement := fmt.Sprintf(moduleConfigTemplate, module.PlaceholderSgAppModuleConfig) + content = replacer.Replace(content, module.PlaceholderSgAppModuleConfig, moduleConfigReplacement) + + // preblocker for migrationmngr + preBlockerTemplate := `migrationmngrtypes.ModuleName, + %[1]v` + preBlockerReplacement := fmt.Sprintf(preBlockerTemplate, "// this line is used by starport scaffolding # stargate/app/preBlockers") + content = replacer.Replace(content, "// this line is used by starport scaffolding # stargate/app/preBlockers", preBlockerReplacement) + + // end block for migrationmngr + endBlockerTemplate := `migrationmngrtypes.ModuleName, +%[1]v` + endBlockerReplacement := fmt.Sprintf(endBlockerTemplate, module.PlaceholderSgAppEndBlockers) + content = replacer.Replace(content, module.PlaceholderSgAppEndBlockers, endBlockerReplacement) + } + + // replace staking blank import + content, err = xast.RemoveImports(content, + xast.WithNamedImport("_", "github.com/cosmos/cosmos-sdk/x/staking"), + ) + if err != nil { + return err + } + + if content, err = xast.AppendImports(content, + xast.WithNamedImport("_", "github.com/evstack/ev-abci/modules/staking"), + ); err != nil { + return err + } + + return r.File(genny.NewFileS(configPath, content)) } - gomod.AddNewRequire(EvABCIPackage, EvABCIVersion, false) - gomod.AddNewRequire(EvNodePackage, EvNodeVersion, false) + appGoModify := func(r *genny.Runner) error { + configPath := filepath.Join(appPath, module.PathAppGo) + f, err := r.Disk.Find(configPath) + if err != nil { + return err + } - // add local-da as go tool dependency (useful for local development) - if err := gomod.AddTool(EvNodeDaCmd); err != nil { - return errors.Errorf("failed to add local-da tool: %w", err) + // replace staking import + content, err := xast.RemoveImports(f.String(), + xast.WithNamedImport("stakingkeeper", "github.com/cosmos/cosmos-sdk/x/staking/keeper"), + ) + if err != nil { + return err + } + + if content, err = xast.AppendImports(content, + xast.WithNamedImport("stakingkeeper", "github.com/evstack/ev-abci/modules/staking/keeper"), + ); err != nil { + return err + } + + return r.File(genny.NewFileS(configPath, content)) } - // add required replaces - gomod.AddReplace(GoHeaderPackage, "", GoHeaderPackageFork, GoHeaderVersionFork) + exportModify := func(r *genny.Runner) error { + configPath := filepath.Join(appPath, filepath.Join(module.PathAppModule, "export.go")) + f, err := r.Disk.Find(configPath) + if err != nil { + return err + } + + content := strings.ReplaceAll(f.String(), "staking.WriteValidators(ctx, app.StakingKeeper)", "staking.WriteValidators(ctx, app.StakingKeeper.Keeper)") - // save go.mod - data, err := gomod.Format() - if err != nil { - return errors.Errorf("failed to format go.mod: %w", err) + return r.File(genny.NewFileS(configPath, content)) } - return os.WriteFile(filepath.Join(appPath, "go.mod"), data, 0o644) + return func(r *genny.Runner) error { + err := appConfigModify(r, withMigration) + err = errors.Join(err, exportModify(r)) + err = errors.Join(err, appGoModify(r)) + + return err + } } // replaceLegacyAddCommands replaces the legacy `AddCommands` with a temporary `AddCommandsWithStartCmdOptions` boilerplate. diff --git a/evolve/template/migrate.go b/evolve/template/migrate.go index fc44bdca..80a69230 100644 --- a/evolve/template/migrate.go +++ b/evolve/template/migrate.go @@ -1,94 +1,40 @@ package template import ( - "errors" - "fmt" "path/filepath" - "strings" "github.com/gobuffalo/genny/v2" - "github.com/ignite/cli/v29/ignite/pkg/placeholder" "github.com/ignite/cli/v29/ignite/pkg/xast" - "github.com/ignite/cli/v29/ignite/templates/module" ) -// migrateFromCometModify modifies the app to add the migration from cometbft commands and modules. -func migrateFromCometModify(appPath string) genny.RunFn { - replacer := placeholder.New() - - appConfigModify := func(r *genny.Runner) error { - configPath := filepath.Join(appPath, module.PathAppConfigGo) - f, err := r.Disk.Find(configPath) +// commandsMigrateModify adds the evolve migrate command to the application. +func commandsMigrateModify(appPath, binaryName string) genny.RunFn { + return func(r *genny.Runner) error { + cmdPath := filepath.Join(appPath, "cmd", binaryName, "cmd", "commands.go") + f, err := r.Disk.Find(cmdPath) if err != nil { return err } - // Import migrationmngr module - content, err := xast.AppendImports(f.String(), - xast.WithNamedImport("migrationmngrmodule", "github.com/evstack/ev-abci/modules/migrationmngr/module"), - xast.WithNamedImport("migrationmngrtypes", "github.com/evstack/ev-abci/modules/migrationmngr/types"), - xast.WithNamedImport("_", "github.com/evstack/ev-abci/modules/migrationmngr"), + content, err := xast.AppendImports( + f.String(), + xast.WithNamedImport("abciserver", "github.com/evstack/ev-abci/server"), ) if err != nil { return err } - // add migrationmngr module config for depinject - moduleConfigTemplate := `{ - Name: migrationmngrtypes.ModuleName, - Config: appconfig.WrapAny(&migrationmngrmodule.Module{}), - }, - %[1]v` - moduleConfigReplacement := fmt.Sprintf(moduleConfigTemplate, module.PlaceholderSgAppModuleConfig) - content = replacer.Replace(content, module.PlaceholderSgAppModuleConfig, moduleConfigReplacement) - - // preblocker for migrationmngr - preBlockerTemplate := `migrationmngrtypes.ModuleName, - %[1]v` - preBlockerReplacement := fmt.Sprintf(preBlockerTemplate, "// this line is used by starport scaffolding # stargate/app/preBlockers") - content = replacer.Replace(content, "// this line is used by starport scaffolding # stargate/app/preBlockers", preBlockerReplacement) - - // end block for migrationmngr - endBlockerTemplate := `migrationmngrtypes.ModuleName, -%[1]v` - endBlockerReplacement := fmt.Sprintf(endBlockerTemplate, module.PlaceholderSgAppEndBlockers) - content = replacer.Replace(content, module.PlaceholderSgAppEndBlockers, endBlockerReplacement) - - // replace staking blank import - content = strings.Replace(content, "github.com/cosmos/cosmos-sdk/x/staking", "github.com/evstack/ev-abci/modules/staking", 1) - - return r.File(genny.NewFileS(configPath, content)) - } - - appGoModify := func(r *genny.Runner) error { - configPath := filepath.Join(appPath, module.PathAppGo) - f, err := r.Disk.Find(configPath) - if err != nil { - return err - } - - content := strings.ReplaceAll(f.String(), "github.com/cosmos/cosmos-sdk/x/staking/keeper", "github.com/evstack/ev-abci/modules/staking/keeper") - - return r.File(genny.NewFileS(configPath, content)) - } + // add migrate command + alreadyAdded := false // to avoid adding the migrate command multiple times as there are multiple calls to `rootCmd.AddCommand` + content, err = xast.ModifyCaller(content, "rootCmd.AddCommand", func(args []string) ([]string, error) { + if !alreadyAdded { + args = append(args, evolveV1MigrateCmd) + alreadyAdded = true + } - exportModify := func(r *genny.Runner) error { - configPath := filepath.Join(appPath, filepath.Join(module.PathAppModule, "export.go")) - f, err := r.Disk.Find(configPath) - if err != nil { - return err - } - - content := strings.ReplaceAll(f.String(), "staking.WriteValidators(ctx, app.StakingKeeper)", "staking.WriteValidators(ctx, app.StakingKeeper.Keeper)") - - return r.File(genny.NewFileS(configPath, content)) - } - - return func(r *genny.Runner) error { - err := appConfigModify(r) - err = errors.Join(err, exportModify(r)) - err = errors.Join(err, appGoModify(r)) + return args, nil + }) - return err + return r.File(genny.NewFileS(cmdPath, content)) } }