diff --git a/changelog.md b/changelog.md index 0cc96bd824..d93a62dae8 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ - [#3658](https://github.com/ignite/cli/pull/3658) Rename Marshaler to Codec in EncodingConfig - [#3653](https://github.com/ignite/cli/pull/3653) Add "app" extension to plugin binaries - [#3656](https://github.com/ignite/cli/pull/3656) Disable Go toolchain download +- [#3669](https://github.com/ignite/cli/pull/3669) Rename `plugins` config file to `igniteapps` ### Fixes diff --git a/docs/docs/06-migration/v0.19.2.md b/docs/docs/06-migration/v0.19.2.md index 5bd63a73c1..0ee04f20d3 100644 --- a/docs/docs/06-migration/v0.19.2.md +++ b/docs/docs/06-migration/v0.19.2.md @@ -14,7 +14,7 @@ official Ignite CLI repo which introduces breaking changes. To migrate your chain that was scaffolded with Ignite CLI versions lower than v0.19.2: 1. IBC upgrade: Use - the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v1-to-v2.md) + the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v1-to-v2.md) 2. In your chain's `go.mod` file, remove `tendermint/spm` and add the v0.19.2 version of `tendermint/starport`. If your chain uses these packages, change the import paths as shown: diff --git a/docs/docs/06-migration/v0.26.0.md b/docs/docs/06-migration/v0.26.0.md index 61bf0c5dbb..8dae447d15 100644 --- a/docs/docs/06-migration/v0.26.0.md +++ b/docs/docs/06-migration/v0.26.0.md @@ -17,7 +17,7 @@ their tooling to the latest version. Chains that are newly scaffolded with Ignite CLI `v0.26.0` now use `ibc-go/v6` for ibc functionality. It is not necessary, but recommended to upgrade to the newest version of `ibc-go`. Most migrations can be done by following the -`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md), but there are some +`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md), but there are some specific changes that will need to be followed for Ignite scaffolded chains. ### Removing `cosmosibckeeper` @@ -215,7 +215,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { ### Remaining migration -After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md). +After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md). ## Scaffolded Release Workflow diff --git a/docs/docs/06-migration/v0.28.0.md b/docs/docs/06-migration/v0.28.0.md new file mode 100644 index 0000000000..5484d9d482 --- /dev/null +++ b/docs/docs/06-migration/v0.28.0.md @@ -0,0 +1,17 @@ +--- +sidebar_position: 990 +title: v0.28.0 +description: For chains that were scaffolded with Ignite CLI versions lower than v0.28.0. changes are required to use Ignite CLI v0.28.0. +--- + +## Upgrading legacy plugins configuration files + +Ignite `v0.28.0` changes the plugin system which is now called Ignite Apps. This version includes changes +to the CLI command names and the plugin configuration file. + +The plugins configuration file is now called `igniteapps.yml` and the "plugins" section is now called "apps". + +The global plugins directory is now `$HOME/.ignite/apps` instead `$HOME/.ignite/plugins`. + +Updates can be automatically applied by running `ignite doctor` in your blockchain application directory. +Running the command outside your blockchain application directory will only update the global plugins. diff --git a/docs/docs/apps/01-using-apps.md b/docs/docs/apps/01-using-apps.md index 1741496952..459d6c7ea3 100644 --- a/docs/docs/apps/01-using-apps.md +++ b/docs/docs/apps/01-using-apps.md @@ -9,7 +9,7 @@ core concepts within apps: `Commands` and `Hooks`. `Commands` extend the CLI's functionality and `Hooks` extend existing CLI command functionality. Apps are registered in an Ignite scaffolded blockchain project through the -`plugins.yml`, or globally through `$HOME/.ignite/plugins/plugins.yml`. +`igniteapps.yml`, or globally through `$HOME/.ignite/apps/igniteapps.yml`. To use an app within your project execute the following command inside the project directory: diff --git a/docs/versioned_docs/version-v0.25.2/contributing/02-technical-setup.md b/docs/versioned_docs/version-v0.25.2/contributing/02-technical-setup.md index d295f14b76..849e194304 100644 --- a/docs/versioned_docs/version-v0.25.2/contributing/02-technical-setup.md +++ b/docs/versioned_docs/version-v0.25.2/contributing/02-technical-setup.md @@ -7,7 +7,7 @@ To ensure you have a successful experience working with our Developer Tutorials ## Setting up Visual Studio Code -1. Install [Visual Studio Code](https://vscode-docs.readthedocs.io/en/latest/editor/setup). +1. Install [Visual Studio Code](https://vscode-docs.readthedocs.io/en/latest/editor/setup/). 1. Click **Extensions** in the sidebar. 1. Install this extension: - Go for VS Code The official Go extension for Visual Studio Code diff --git a/docs/versioned_docs/version-v0.25.2/migration/v0.19.2.md b/docs/versioned_docs/version-v0.25.2/migration/v0.19.2.md index d661a0bf19..1b185f7767 100644 --- a/docs/versioned_docs/version-v0.25.2/migration/v0.19.2.md +++ b/docs/versioned_docs/version-v0.25.2/migration/v0.19.2.md @@ -12,7 +12,7 @@ With Ignite CLI v0.19.2, the contents of the deprecated Ignite CLI Modules `tend To migrate your chain that was scaffolded with Ignite CLI versions lower than v0.19.2: -1. IBC upgrade: Use the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v1-to-v2.md) +1. IBC upgrade: Use the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v1-to-v2.md) 2. In your chain's `go.mod` file, remove `tendermint/spm` and add the v0.19.2 version of `tendermint/starport`. If your chain uses these packages, change the import paths as shown: diff --git a/docs/versioned_docs/version-v0.26.1/06-migration/v0.19.2.md b/docs/versioned_docs/version-v0.26.1/06-migration/v0.19.2.md index 5bd63a73c1..0ee04f20d3 100644 --- a/docs/versioned_docs/version-v0.26.1/06-migration/v0.19.2.md +++ b/docs/versioned_docs/version-v0.26.1/06-migration/v0.19.2.md @@ -14,7 +14,7 @@ official Ignite CLI repo which introduces breaking changes. To migrate your chain that was scaffolded with Ignite CLI versions lower than v0.19.2: 1. IBC upgrade: Use - the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v1-to-v2.md) + the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v1-to-v2.md) 2. In your chain's `go.mod` file, remove `tendermint/spm` and add the v0.19.2 version of `tendermint/starport`. If your chain uses these packages, change the import paths as shown: diff --git a/docs/versioned_docs/version-v0.26.1/06-migration/v0.26.0.md b/docs/versioned_docs/version-v0.26.1/06-migration/v0.26.0.md index 61bf0c5dbb..8dae447d15 100644 --- a/docs/versioned_docs/version-v0.26.1/06-migration/v0.26.0.md +++ b/docs/versioned_docs/version-v0.26.1/06-migration/v0.26.0.md @@ -17,7 +17,7 @@ their tooling to the latest version. Chains that are newly scaffolded with Ignite CLI `v0.26.0` now use `ibc-go/v6` for ibc functionality. It is not necessary, but recommended to upgrade to the newest version of `ibc-go`. Most migrations can be done by following the -`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md), but there are some +`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md), but there are some specific changes that will need to be followed for Ignite scaffolded chains. ### Removing `cosmosibckeeper` @@ -215,7 +215,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { ### Remaining migration -After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md). +After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md). ## Scaffolded Release Workflow diff --git a/docs/versioned_docs/version-v0.27.1/06-migration/v0.19.2.md b/docs/versioned_docs/version-v0.27.1/06-migration/v0.19.2.md index 5bd63a73c1..0ee04f20d3 100644 --- a/docs/versioned_docs/version-v0.27.1/06-migration/v0.19.2.md +++ b/docs/versioned_docs/version-v0.27.1/06-migration/v0.19.2.md @@ -14,7 +14,7 @@ official Ignite CLI repo which introduces breaking changes. To migrate your chain that was scaffolded with Ignite CLI versions lower than v0.19.2: 1. IBC upgrade: Use - the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v1-to-v2.md) + the [IBC migration documents](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v1-to-v2.md) 2. In your chain's `go.mod` file, remove `tendermint/spm` and add the v0.19.2 version of `tendermint/starport`. If your chain uses these packages, change the import paths as shown: diff --git a/docs/versioned_docs/version-v0.27.1/06-migration/v0.26.0.md b/docs/versioned_docs/version-v0.27.1/06-migration/v0.26.0.md index 61bf0c5dbb..8dae447d15 100644 --- a/docs/versioned_docs/version-v0.27.1/06-migration/v0.26.0.md +++ b/docs/versioned_docs/version-v0.27.1/06-migration/v0.26.0.md @@ -17,7 +17,7 @@ their tooling to the latest version. Chains that are newly scaffolded with Ignite CLI `v0.26.0` now use `ibc-go/v6` for ibc functionality. It is not necessary, but recommended to upgrade to the newest version of `ibc-go`. Most migrations can be done by following the -`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md), but there are some +`ibc-go` [migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md), but there are some specific changes that will need to be followed for Ignite scaffolded chains. ### Removing `cosmosibckeeper` @@ -215,7 +215,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { ### Remaining migration -After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/main/docs/migrations/v5-to-v6.md). +After all uses of `cosmosibckeeper` have been removed, you can follow any remaining steps in the`ibc-go`[migration guide](https://github.com/cosmos/ibc-go/blob/v6.2.0/docs/migrations/v5-to-v6.md). ## Scaffolded Release Workflow diff --git a/ignite/cmd/doctor.go b/ignite/cmd/doctor.go index 2d0b9cc277..072b6d5edb 100644 --- a/ignite/cmd/doctor.go +++ b/ignite/cmd/doctor.go @@ -22,6 +22,10 @@ func NewDoctor() *cobra.Command { return err } + if err := doc.MigratePluginsConfig(); err != nil { + return err + } + return doc.FixDependencyTools(cmd.Context()) }, } diff --git a/ignite/cmd/plugin.go b/ignite/cmd/plugin.go index f93e7a39f8..64e77048fb 100644 --- a/ignite/cmd/plugin.go +++ b/ignite/cmd/plugin.go @@ -39,12 +39,12 @@ func LoadPlugins(ctx context.Context, cmd *cobra.Command) error { if err != nil && !errors.As(err, &cosmosanalysis.ErrPathNotChain{}) { return err } else if err == nil { - pluginsConfigs = append(pluginsConfigs, localCfg.Plugins...) + pluginsConfigs = append(pluginsConfigs, localCfg.Apps...) } globalCfg, err := parseGlobalPlugins() if err == nil { - pluginsConfigs = append(pluginsConfigs, globalCfg.Plugins...) + pluginsConfigs = append(pluginsConfigs, globalCfg.Apps...) } ensureDefaultPlugins(cmd, globalCfg) @@ -97,8 +97,8 @@ func parseGlobalPlugins() (cfg *pluginsconfig.Config, err error) { return &pluginsconfig.Config{}, nil } - for i := range cfg.Plugins { - cfg.Plugins[i].Global = true + for i := range cfg.Apps { + cfg.Apps[i].Global = true } return } @@ -436,7 +436,7 @@ Example: return err } - for _, p := range conf.Plugins { + for _, p := range conf.Apps { if p.Path == args[0] { return fmt.Errorf("cannot add duplicate plugin %s", args[0]) } @@ -476,7 +476,7 @@ Example: return fmt.Errorf("error while loading plugin %q: %w", args[0], plugins[0].Error) } session.Println("Done loading plugin") - conf.Plugins = append(conf.Plugins, p) + conf.Apps = append(conf.Apps, p) if err := conf.Save(); err != nil { return err @@ -517,9 +517,9 @@ func NewPluginRemove() *cobra.Command { } removed := false - for i, cp := range conf.Plugins { + for i, cp := range conf.Apps { if cp.Path == args[0] { - conf.Plugins = append(conf.Plugins[:i], conf.Plugins[i+1:]...) + conf.Apps = append(conf.Apps[:i], conf.Apps[i+1:]...) removed = true break } @@ -658,8 +658,7 @@ func printPlugins(session *cliui.Session) error { func flagSetPluginsGlobal() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - fs.BoolP(flagPluginsGlobal, "g", false, "use global plugins configuration"+ - " ($HOME/.ignite/plugins/plugins.yml)") + fs.BoolP(flagPluginsGlobal, "g", false, "use global plugins configuration ($HOME/.ignite/apps/igniteapps.yml)") return fs } diff --git a/ignite/cmd/plugin_default.go b/ignite/cmd/plugin_default.go index 17b564be1d..a7a2424197 100644 --- a/ignite/cmd/plugin_default.go +++ b/ignite/cmd/plugin_default.go @@ -74,7 +74,7 @@ func newPluginInstallCmd(dp defaultPlugin) *cobra.Command { pluginCfg := pluginsconfig.Plugin{ Path: dp.path, } - cfg.Plugins = append(cfg.Plugins, pluginCfg) + cfg.Apps = append(cfg.Apps, pluginCfg) if err := cfg.Save(); err != nil { return err } diff --git a/ignite/cmd/plugin_default_test.go b/ignite/cmd/plugin_default_test.go index 04528f14ec..bf2d4a4c5e 100644 --- a/ignite/cmd/plugin_default_test.go +++ b/ignite/cmd/plugin_default_test.go @@ -23,7 +23,7 @@ func TestEnsureDefaultPlugins(t *testing.T) { { name: "should not add because already present in config", cfg: &pluginsconfig.Config{ - Plugins: []pluginsconfig.Plugin{{ + Apps: []pluginsconfig.Plugin{{ Path: "github.com/ignite/cli-plugin-network@v42", }}, }, diff --git a/ignite/config/chain/v1/testdata/config2.yaml b/ignite/config/chain/v1/testdata/config2.yaml index ea1b8d2822..38c2fe42c8 100644 --- a/ignite/config/chain/v1/testdata/config2.yaml +++ b/ignite/config/chain/v1/testdata/config2.yaml @@ -37,7 +37,7 @@ validators: address: 0.0.0.0:8545 ws-address: 0.0.0.0:8546 home: $HOME/.evmosd -plugins: +apps: - name: plugin1 path: /path/to/plugin1 - name: plugin2 diff --git a/ignite/config/plugins/config.go b/ignite/config/plugins/config.go index e2740eeb84..4c5bf2e05b 100644 --- a/ignite/config/plugins/config.go +++ b/ignite/config/plugins/config.go @@ -16,7 +16,9 @@ type Config struct { // path to the config file path string - Plugins []Plugin `yaml:"plugins"` + // Apps holds the list of installed Ignite Apps. + // Ignite Apps are implemented as plugins. + Apps []Plugin `yaml:"apps"` } // Plugin keeps plugin name and location. @@ -38,10 +40,12 @@ type Plugin struct { // // path: github.com/foo/bar/plugin1@v42 Path string `yaml:"path"` + // With holds arguments passed to the plugin interface With map[string]string `yaml:"with,omitempty"` + // Global holds whether the plugin is installed globally - // (default: $HOME/.ignite/plugins/plugins.yml) or locally for a chain. + // (default: $HOME/.ignite/apps/igniteapps.yml) or locally for a chain. Global bool `yaml:"-"` } @@ -134,7 +138,7 @@ func (c *Config) Save() error { // Returns also true if there's a local plugin with the module name equal to // that path. func (c Config) HasPlugin(path string) bool { - return slices.ContainsFunc(c.Plugins, func(cp Plugin) bool { + return slices.ContainsFunc(c.Apps, func(cp Plugin) bool { if cp.HasPath(path) { return true } diff --git a/ignite/config/plugins/config_test.go b/ignite/config/plugins/config_test.go index b560b6f770..5986efe8ad 100644 --- a/ignite/config/plugins/config_test.go +++ b/ignite/config/plugins/config_test.go @@ -268,30 +268,30 @@ func TestConfigSave(t *testing.T) { require.NoError(t, err) return cfg }, - expectedContent: "plugins: []\n", + expectedContent: "apps: []\n", }, { name: "ok: config path is an existing file", buildConfig: func(t *testing.T) *pluginsconfig.Config { - // copy testdata/plugins.yml to tmp because it will be modified + // copy testdata/igniteapps.yml to tmp because it will be modified dir := t.TempDir() - bz, err := os.ReadFile("testdata/plugins.yml") + bz, err := os.ReadFile("testdata/igniteapps.yml") require.NoError(t, err) - err = os.WriteFile(path.Join(dir, "plugins.yml"), bz, 0o666) + err = os.WriteFile(path.Join(dir, "igniteapps.yml"), bz, 0o666) require.NoError(t, err) // load from tmp cfg, _ := pluginsconfig.ParseDir(dir) // add a new plugin - cfg.Plugins = append(cfg.Plugins, pluginsconfig.Plugin{ + cfg.Apps = append(cfg.Apps, pluginsconfig.Plugin{ Path: "/path/to/plugin3", With: map[string]string{"key": "val"}, }) // update a plugin - cfg.Plugins[1].Path = "/path/to/plugin22" - cfg.Plugins[1].With["key"] = "val" + cfg.Apps[1].Path = "/path/to/plugin22" + cfg.Apps[1].With["key"] = "val" return cfg }, - expectedContent: `plugins: + expectedContent: `apps: - path: /path/to/plugin1 - path: /path/to/plugin22 with: @@ -338,7 +338,7 @@ func TestConfigHasPlugin(t *testing.T) { { name: "not found in config", cfg: pluginsconfig.Config{ - Plugins: []pluginsconfig.Plugin{ + Apps: []pluginsconfig.Plugin{ {Path: "github.com/ignite/example2"}, }, }, @@ -347,7 +347,7 @@ func TestConfigHasPlugin(t *testing.T) { { name: "found in config", cfg: pluginsconfig.Config{ - Plugins: []pluginsconfig.Plugin{ + Apps: []pluginsconfig.Plugin{ {Path: "github.com/ignite/example2"}, {Path: "github.com/ignite/example@master"}, }, @@ -357,7 +357,7 @@ func TestConfigHasPlugin(t *testing.T) { { name: "found in config but from a local plugin", cfg: pluginsconfig.Config{ - Plugins: []pluginsconfig.Plugin{ + Apps: []pluginsconfig.Plugin{ {Path: "github.com/ignite/example2"}, {Path: path.Join(wd, "testdata", "localplugin", "example")}, }, diff --git a/ignite/config/plugins/parse.go b/ignite/config/plugins/parse.go index 589cc5c1d6..e823500e18 100644 --- a/ignite/config/plugins/parse.go +++ b/ignite/config/plugins/parse.go @@ -12,7 +12,7 @@ import ( // ParseDir expects to find a plugin config file in dir. If dir is not a folder, // an error is returned. -// The plugin config file format can be `plugins.yml` or `plugins.yaml`. If +// The plugin config file format can be `igniteapps.yml` or `igniteapps.yaml`. If // found, the file is parsed into a Config and returned. If no file from the // given names above are found, then an empty config is returned, w/o errors. func ParseDir(dir string) (*Config, error) { @@ -53,8 +53,7 @@ func ParseDir(dir string) (*Config, error) { } var ( - // filenames is a list of recognized names as Ignite's plugins config file. - filenames = []string{"plugins.yml", "plugins.yaml"} + filenames = []string{"igniteapps.yml", "igniteapps.yaml"} defaultFilename = filenames[0] ) diff --git a/ignite/config/plugins/parse_test.go b/ignite/config/plugins/parse_test.go index 230fe28fbd..abe7558e3a 100644 --- a/ignite/config/plugins/parse_test.go +++ b/ignite/config/plugins/parse_test.go @@ -18,8 +18,8 @@ func TestParseDir(t *testing.T) { }{ { name: "fail: path is not a dir", - path: "testdata/plugins.yml", - expectedError: "plugin config parse: path testdata/plugins.yml is not a dir", + path: "testdata/igniteapps.yml", + expectedError: "plugin config parse: path testdata/igniteapps.yml is not a dir", }, { name: "fail: path doesn't exists", @@ -30,7 +30,7 @@ func TestParseDir(t *testing.T) { name: "ok: path doesn't contain any config", path: "testdata/noconfig", expectedPlugins: nil, - expectedPath: "testdata/noconfig/plugins.yml", + expectedPath: "testdata/noconfig/igniteapps.yml", }, { name: "fail: path contains an invalid yml file", @@ -52,7 +52,7 @@ func TestParseDir(t *testing.T) { }, }, }, - expectedPath: "testdata/plugins.yml", + expectedPath: "testdata/igniteapps.yml", }, { name: "ok: path contains a plugin.yaml file", @@ -69,7 +69,7 @@ func TestParseDir(t *testing.T) { }, }, }, - expectedPath: "testdata/other/plugins.yaml", + expectedPath: "testdata/other/igniteapps.yaml", }, } for _, tt := range tests { @@ -83,7 +83,7 @@ func TestParseDir(t *testing.T) { return } require.NoError(err) - require.Equal(tt.expectedPlugins, cfg.Plugins) + require.Equal(tt.expectedPlugins, cfg.Apps) require.Equal(tt.expectedPath, cfg.Path()) }) } diff --git a/ignite/config/plugins/testdata/other/plugins.yaml b/ignite/config/plugins/testdata/igniteapps.yml similarity index 93% rename from ignite/config/plugins/testdata/other/plugins.yaml rename to ignite/config/plugins/testdata/igniteapps.yml index 9e268110e2..2d541a7553 100644 --- a/ignite/config/plugins/testdata/other/plugins.yaml +++ b/ignite/config/plugins/testdata/igniteapps.yml @@ -1,4 +1,4 @@ -plugins: +apps: - name: plugin1 path: /path/to/plugin1 - name: plugin2 diff --git a/ignite/config/plugins/testdata/invalid/plugins.yml b/ignite/config/plugins/testdata/invalid/igniteapps.yml similarity index 100% rename from ignite/config/plugins/testdata/invalid/plugins.yml rename to ignite/config/plugins/testdata/invalid/igniteapps.yml diff --git a/ignite/config/plugins/testdata/plugins.yml b/ignite/config/plugins/testdata/other/igniteapps.yaml similarity index 93% rename from ignite/config/plugins/testdata/plugins.yml rename to ignite/config/plugins/testdata/other/igniteapps.yaml index 9e268110e2..2d541a7553 100644 --- a/ignite/config/plugins/testdata/plugins.yml +++ b/ignite/config/plugins/testdata/other/igniteapps.yaml @@ -1,4 +1,4 @@ -plugins: +apps: - name: plugin1 path: /path/to/plugin1 - name: plugin2 diff --git a/ignite/internal/tools/gen-cli-docs/main.go b/ignite/internal/tools/gen-cli-docs/main.go index 56ead1c6df..b07cfd4502 100644 --- a/ignite/internal/tools/gen-cli-docs/main.go +++ b/ignite/internal/tools/gen-cli-docs/main.go @@ -58,7 +58,7 @@ func run(outPath string) error { if err != nil { return err } - cfg.Plugins = append(cfg.Plugins, pluginsconfig.Plugin{ + cfg.Apps = append(cfg.Apps, pluginsconfig.Plugin{ // Add network plugin Path: ignitecmd.PluginNetworkPath, }) diff --git a/ignite/pkg/cliui/cliui.go b/ignite/pkg/cliui/cliui.go index 089aad3f57..fbbc098f2e 100644 --- a/ignite/pkg/cliui/cliui.go +++ b/ignite/pkg/cliui/cliui.go @@ -289,6 +289,7 @@ func (s *Session) handleEvents() { s.StopSpinner() fmt.Fprintf(stdout, "%s\n", e) case events.IndicationNone: + fallthrough default: // The text printed here won't be removed when the spinner stops resume := s.PauseSpinner() diff --git a/ignite/pkg/events/events.go b/ignite/pkg/events/events.go index 8b0a7202a8..d5a47d79cf 100644 --- a/ignite/pkg/events/events.go +++ b/ignite/pkg/events/events.go @@ -2,7 +2,11 @@ // for others to consume and display to end users in meaningful ways. package events -import "fmt" +import ( + "fmt" + + "github.com/muesli/reflow/indent" +) // ProgressIndication enumerates possible states of progress indication for an Event. type ProgressIndication uint8 @@ -23,6 +27,7 @@ type ( Event struct { ProgressIndication ProgressIndication Icon string + Indent uint Message string Verbose bool Group string @@ -67,6 +72,13 @@ func Icon(icon string) Option { } } +// Indent sets the text indentation. +func Indent(indent uint) Option { + return func(e *Event) { + e.Indent = indent + } +} + // Group sets a group name for the event. func Group(name string) Option { return func(e *Event) { @@ -86,11 +98,16 @@ func New(message string, options ...Option) Event { } func (e Event) String() string { + s := e.Message if e.Icon != "" { - return fmt.Sprintf("%s %s", e.Icon, e.Message) + s = fmt.Sprintf("%s %s", e.Icon, s) + } + + if e.Indent > 0 { + s = indent.String(s, e.Indent) } - return e.Message + return s } // InProgress returns true when the event is in progress. diff --git a/ignite/services/doctor/doctor.go b/ignite/services/doctor/doctor.go index 51f791236a..95f873ea63 100644 --- a/ignite/services/doctor/doctor.go +++ b/ignite/services/doctor/doctor.go @@ -55,7 +55,7 @@ func (d *Doctor) MigrateConfig(_ context.Context) error { return fmt.Errorf("doctor migrate config: %w", err) } - d.ev.Send("Checking chain config file:", events.ProgressFinish()) + d.ev.Send("Checking chain config file:") configPath, err := chainconfig.LocateDefault(".") if err != nil { @@ -95,6 +95,7 @@ func (d *Doctor) MigrateConfig(_ context.Context) error { d.ev.Send( fmt.Sprintf("config file %s", colors.Success(status)), events.Icon(icons.OK), + events.Indent(1), events.ProgressFinish(), ) @@ -109,7 +110,7 @@ func (d *Doctor) FixDependencyTools(ctx context.Context) error { return fmt.Errorf("doctor fix dependency tools: %w", err) } - d.ev.Send("Checking dependency tools:", events.ProgressFinish()) + d.ev.Send("Checking dependency tools:") _, err := os.Stat(ToolsFile) @@ -118,7 +119,7 @@ func (d *Doctor) FixDependencyTools(ctx context.Context) error { d.ev.Send( fmt.Sprintf("%s %s", ToolsFile, colors.Success("exists")), events.Icon(icons.OK), - events.ProgressUpdate(), + events.Indent(1), ) updated, err := d.ensureDependencyImports(ToolsFile) @@ -134,6 +135,7 @@ func (d *Doctor) FixDependencyTools(ctx context.Context) error { d.ev.Send( fmt.Sprintf("tools file %s", colors.Success(status)), events.Icon(icons.OK), + events.Indent(1), events.ProgressFinish(), ) @@ -142,6 +144,12 @@ func (d *Doctor) FixDependencyTools(ctx context.Context) error { return errf(err) } + d.ev.Send( + fmt.Sprintf("tools file %s", colors.Success("created")), + events.Icon(icons.OK), + events.Indent(1), + ) + default: return errf(err) } @@ -177,10 +185,10 @@ func (d Doctor) createToolsFile(ctx context.Context, toolsFilename string) error d.ev.Send( fmt.Sprintf("%s %s", toolsFilename, colors.Success("created")), events.Icon(icons.OK), - events.ProgressFinish(), + events.Indent(1), ) - d.ev.Send("Installing dependency tools", events.ProgressStart()) + d.ev.Send("Installing dependency tools", events.ProgressUpdate()) if err := cosmosgen.InstallDepTools(ctx, "."); err != nil { return err } @@ -189,7 +197,7 @@ func (d Doctor) createToolsFile(ctx context.Context, toolsFilename string) error d.ev.Send( fmt.Sprintf("%s %s", path.Base(dep), colors.Success("installed")), events.Icon(icons.OK), - events.ProgressFinish(), + events.Indent(1), ) } @@ -225,5 +233,12 @@ func (d Doctor) ensureDependencyImports(toolsFilename string) (bool, error) { return false, err } + d.ev.Send( + fmt.Sprintf("tools dependencies %s", colors.Success("OK")), + events.Icon(icons.OK), + events.Indent(1), + events.ProgressFinish(), + ) + return true, nil } diff --git a/ignite/services/doctor/doctor_plugins.go b/ignite/services/doctor/doctor_plugins.go new file mode 100644 index 0000000000..fdc1ce4bc5 --- /dev/null +++ b/ignite/services/doctor/doctor_plugins.go @@ -0,0 +1,210 @@ +package doctor + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" + + "github.com/ignite/cli/ignite/config" + chainconfig "github.com/ignite/cli/ignite/config/chain" + "github.com/ignite/cli/ignite/pkg/cliui/colors" + "github.com/ignite/cli/ignite/pkg/cliui/icons" + "github.com/ignite/cli/ignite/pkg/events" +) + +// MigratePluginsConfig migrates plugins config to Ignite App config if required. +func (d Doctor) MigratePluginsConfig() error { + errf := func(err error) error { + return fmt.Errorf("doctor migrate plugins config: %w", err) + } + + d.ev.Send("Checking for legacy plugin config files:") + d.ev.Send("Searching global plugins config file", events.ProgressStart()) + + if err := d.migrateGlobalPluginConfig(); err != nil { + return errf(err) + } + + d.ev.Send("Searching local plugins config file", events.ProgressUpdate()) + + if err := d.migrateLocalPluginsConfig(); err != nil { + return errf(err) + } + + d.ev.Send( + fmt.Sprintf("plugin config files %s", colors.Success("OK")), + events.Icon(icons.OK), + events.Indent(1), + events.ProgressFinish(), + ) + + return nil +} + +func (d Doctor) migrateGlobalPluginConfig() error { + globalPath, err := config.DirPath() + if err != nil { + return err + } + + // Global apps directory is always available because it is + // created if it doesn't exists when any command is executed. + appsPath := filepath.Join(globalPath, "apps", "igniteapps.yml") + if _, err := os.Stat(appsPath); err == nil { + d.ev.Send( + fmt.Sprintf("%s %s", appsPath, colors.Success("exists")), + events.Icon(icons.OK), + events.Indent(1), + ) + + // Ignite apps config file exists in global directory + return nil + } + + legacyPath, err := findPluginsConfigPath(filepath.Join(globalPath, "plugins")) + if err != nil { + return err + } else if legacyPath == "" { + // Nothing to migrate when the legacy plugins config path doesn't exist + return nil + } + + if err := d.migratePluginsConfigFiles(legacyPath, appsPath); err != nil { + return err + } + + d.ev.SendInfo( + fmt.Sprintf("directory %s can safely be removed", filepath.Dir(legacyPath)), + events.Icon(icons.Info), + events.Indent(1), + ) + + return nil +} + +func (d Doctor) migrateLocalPluginsConfig() error { + localPath, err := chainconfig.LocateDefault(".") + if err != nil { + if errors.Is(err, chainconfig.ErrConfigNotFound) { + // When app config is not found it means the doctor + // command is not being run within a blockchain app, + // so there is not local config to migrate + return nil + } + + return err + } + + localPath, err = filepath.Abs(filepath.Dir(localPath)) + if err != nil { + return err + } + + appsPath := filepath.Join(localPath, "igniteapps.yml") + if _, err := os.Stat(appsPath); err == nil { + d.ev.Send( + fmt.Sprintf("%s %s", appsPath, colors.Success("exists")), + events.Icon(icons.OK), + events.Indent(1), + ) + + // Ignite apps config file exists in current directory + return nil + } + + legacyPath, err := findPluginsConfigPath(localPath) + if err != nil { + return err + } else if legacyPath == "" { + // Nothing to migrate when plugins config file is not found in current directory + return nil + } + + return d.migratePluginsConfigFiles(legacyPath, appsPath) +} + +func (d Doctor) migratePluginsConfigFiles(pluginsPath, appsPath string) error { + pluginsFile, err := os.Open(pluginsPath) + if err != nil { + return err + } + + defer pluginsFile.Close() + + appsFile, err := os.OpenFile(appsPath, os.O_WRONLY|os.O_CREATE, 0o644) + if err != nil { + return err + } + + defer appsFile.Close() + + if err = migratePluginsConfig(pluginsFile, appsFile); err != nil { + return err + } + + d.ev.Send( + fmt.Sprintf("migrated config file %s to %s", colors.Faint(pluginsPath), colors.Faint(appsPath)), + events.Icon(icons.OK), + events.Indent(1), + ) + d.ev.SendInfo( + fmt.Sprintf("file %s can safely be removed", pluginsPath), + events.Icon(icons.Info), + events.Indent(1), + ) + + return nil +} + +func migratePluginsConfig(r io.Reader, w io.Writer) error { + bz, err := updatePluginsConfig(r) + if err != nil { + return err + } + + _, err = w.Write(bz) + if err != nil { + return err + } + return nil +} + +func updatePluginsConfig(r io.Reader) ([]byte, error) { + var cfg map[string]any + err := yaml.NewDecoder(r).Decode(&cfg) + if err != nil && !errors.Is(err, io.EOF) { + return nil, err + } + + if apps, ok := cfg["plugins"]; ok { + cfg["apps"] = apps + delete(cfg, "plugins") + } + + var buf bytes.Buffer + if err = yaml.NewEncoder(&buf).Encode(cfg); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func findPluginsConfigPath(dir string) (string, error) { + for _, ext := range []string{"yml", "yaml"} { + path := filepath.Join(dir, fmt.Sprintf("plugins.%s", ext)) + _, err := os.Stat(path) + if err == nil { + // File found + return path, nil + } + + if !os.IsNotExist(err) { + return "", err + } + } + return "", nil +} diff --git a/ignite/services/plugin/plugin.go b/ignite/services/plugin/plugin.go index d1b66d2dbb..28091675a6 100644 --- a/ignite/services/plugin/plugin.go +++ b/ignite/services/plugin/plugin.go @@ -31,7 +31,7 @@ import ( // PluginsPath holds the plugin cache directory. var PluginsPath = xfilepath.Mkdir(xfilepath.Join( config.DirPath, - xfilepath.Path("plugins"), + xfilepath.Path("apps"), )) // Plugin represents a ignite plugin. @@ -76,11 +76,11 @@ func CollectEvents(ev events.Bus) Option { // There's 2 kinds of plugins, local or remote. // Local plugins have their path starting with a `/`, while remote plugins don't. // Local plugins are useful for development purpose. -// Remote plugins require to be fetched first, in $HOME/.ignite/plugins folder, then they are loaded -// from there. +// Remote plugins require to be fetched first, in $HOME/.ignite/apps folder, +// then they are loaded from there. // -// If an error occurs during a plugin load, it's not returned but rather stored in the `Plugin.Error` -// field. This prevents the loading of other plugins to be interrupted. +// If an error occurs during a plugin load, it's not returned but rather stored in +// the `Plugin.Error` field. This prevents the loading of other plugins to be interrupted. func Load(ctx context.Context, plugins []pluginsconfig.Plugin, options ...Option) ([]*Plugin, error) { pluginsDir, err := PluginsPath() if err != nil { @@ -163,8 +163,8 @@ func newPlugin(pluginsDir string, cp pluginsconfig.Plugin, options ...Option) *P p.cloneDir = path.Join(pluginsDir, p.repoPath) } - // Plugin can have a subpath within its repository. For example, - // "github.com/ignite/plugins/plugin1" where "plugin1" is the subpath. + // Plugin can have a subpath within its repository. + // For example, "github.com/ignite/apps/app1" where "app1" is the subpath. repoSubPath := path.Join(parts[3:]...) p.srcPath = path.Join(p.cloneDir, repoSubPath) diff --git a/ignite/services/plugin/plugin_test.go b/ignite/services/plugin/plugin_test.go index 36583953a3..08d59f91b6 100644 --- a/ignite/services/plugin/plugin_test.go +++ b/ignite/services/plugin/plugin_test.go @@ -79,9 +79,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin", + cloneDir: ".ignite/apps/github.com/ignite/plugin", reference: "", - srcPath: ".ignite/plugins/github.com/ignite/plugin", + srcPath: ".ignite/apps/github.com/ignite/plugin", name: "plugin", }, }, @@ -91,9 +91,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin@develop", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin-develop", + cloneDir: ".ignite/apps/github.com/ignite/plugin-develop", reference: "develop", - srcPath: ".ignite/plugins/github.com/ignite/plugin-develop", + srcPath: ".ignite/apps/github.com/ignite/plugin-develop", name: "plugin", }, }, @@ -103,9 +103,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin@package/v1.0.0", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin-package-v1.0.0", + cloneDir: ".ignite/apps/github.com/ignite/plugin-package-v1.0.0", reference: "package/v1.0.0", - srcPath: ".ignite/plugins/github.com/ignite/plugin-package-v1.0.0", + srcPath: ".ignite/apps/github.com/ignite/plugin-package-v1.0.0", name: "plugin", }, }, @@ -115,9 +115,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin", + cloneDir: ".ignite/apps/github.com/ignite/plugin", reference: "", - srcPath: ".ignite/plugins/github.com/ignite/plugin/plugin1", + srcPath: ".ignite/apps/github.com/ignite/plugin/plugin1", name: "plugin1", }, }, @@ -127,9 +127,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin@develop", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin-develop", + cloneDir: ".ignite/apps/github.com/ignite/plugin-develop", reference: "develop", - srcPath: ".ignite/plugins/github.com/ignite/plugin-develop/plugin1", + srcPath: ".ignite/apps/github.com/ignite/plugin-develop/plugin1", name: "plugin1", }, }, @@ -139,9 +139,9 @@ func TestNewPlugin(t *testing.T) { expectedPlugin: Plugin{ repoPath: "github.com/ignite/plugin@package/v1.0.0", cloneURL: "https://github.com/ignite/plugin", - cloneDir: ".ignite/plugins/github.com/ignite/plugin-package-v1.0.0", + cloneDir: ".ignite/apps/github.com/ignite/plugin-package-v1.0.0", reference: "package/v1.0.0", - srcPath: ".ignite/plugins/github.com/ignite/plugin-package-v1.0.0/plugin1", + srcPath: ".ignite/apps/github.com/ignite/plugin-package-v1.0.0/plugin1", name: "plugin1", }, }, @@ -150,7 +150,7 @@ func TestNewPlugin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { tt.expectedPlugin.Plugin = tt.pluginCfg - p := newPlugin(".ignite/plugins", tt.pluginCfg) + p := newPlugin(".ignite/apps", tt.pluginCfg) assertPlugin(t, tt.expectedPlugin, *p) }) diff --git a/integration/plugin/plugin_test.go b/integration/plugin/plugin_test.go index fa67287c5d..551ce600ee 100644 --- a/integration/plugin/plugin_test.go +++ b/integration/plugin/plugin_test.go @@ -23,13 +23,13 @@ func TestAddRemovePlugin(t *testing.T) { assertPlugins = func(expectedLocalPlugins, expectedGlobalPlugins []pluginsconfig.Plugin) { localCfg, err := pluginsconfig.ParseDir(app.SourcePath()) require.NoError(err) - assert.ElementsMatch(expectedLocalPlugins, localCfg.Plugins, "unexpected local plugins") + assert.ElementsMatch(expectedLocalPlugins, localCfg.Apps, "unexpected local plugins") globalCfgPath, err := plugin.PluginsPath() require.NoError(err) globalCfg, err := pluginsconfig.ParseDir(globalCfgPath) require.NoError(err) - assert.ElementsMatch(expectedGlobalPlugins, globalCfg.Plugins, "unexpected global plugins") + assert.ElementsMatch(expectedGlobalPlugins, globalCfg.Apps, "unexpected global plugins") } )