Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: separate plugins.yml file #3184

Merged
merged 44 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d4ca56b
base
Nov 28, 2022
93c1ad5
base refactor
Nov 28, 2022
ee162da
refactor
Nov 28, 2022
8303068
rename
Nov 28, 2022
6565fc5
rename
Nov 28, 2022
863876f
fix comment
Nov 28, 2022
eaccb71
rename file
Nov 28, 2022
c490fa5
format
Nov 28, 2022
844c83b
refactor base
Nov 28, 2022
82e9ac0
format
Nov 28, 2022
a8592a5
refactor some imports
Nov 28, 2022
1d5bd3e
imports refactor
Nov 28, 2022
15e543a
fix
Nov 28, 2022
2cf58e4
fix import
Nov 28, 2022
4d986c3
Merge branch 'main' into feat/plugins-refacotr
Nov 28, 2022
5f8c837
refactor:
Nov 28, 2022
1459f1c
changelog
Nov 28, 2022
365df2d
Merge branch 'main' into feat/separate-plugins-config
Nov 28, 2022
ea5434a
changelog
Nov 28, 2022
1a3167e
Update ignite/services/network/networkchain/init.go
Nov 28, 2022
0ad9f3d
base -> baseconfig
Nov 28, 2022
360bc17
refactoring for clarity
Nov 28, 2022
71a75aa
v12 -> v1
Nov 28, 2022
9b89846
fix tests
Nov 28, 2022
a69a758
fix integration
Nov 28, 2022
f74180a
fix name
Nov 28, 2022
b57ac11
fix integration
Nov 28, 2022
6d081b6
Merge branch 'main' into feat/plugins-refacotr
Nov 28, 2022
7408d51
merge
Nov 28, 2022
db2ed00
format
Nov 28, 2022
1620580
merge main
Nov 28, 2022
8d24282
Merge branch 'main' into feat/separate-plugins-config
Nov 28, 2022
a40d3dc
Update ignite/cmd/cmd.go
Nov 29, 2022
e685899
imports
Nov 29, 2022
aa57e74
Merge branch 'main' into feat/separate-plugins-config
Nov 29, 2022
5c429be
LocateDefault logic
Nov 29, 2022
a6c78e9
lint fix
Nov 29, 2022
f0bde05
Merge branch 'main' into feat/separate-plugins-config
Nov 29, 2022
54e7fe3
refactor and test
Nov 29, 2022
39e92e7
finish refactor
Nov 29, 2022
9f10308
revert
Nov 29, 2022
b0e3722
Merge branch 'main' into feat/separate-plugins-config
Nov 30, 2022
631d64e
address review
Nov 30, 2022
e2d5f56
testdata
Nov 30, 2022
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 changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Features

- [#3184](https://github.com/ignite/cli/pull/3184) Separate `plugins.yml` config file.
- [#3038](https://github.com/ignite/cli/pull/3038) Addition of Plugin Hooks in Plugin System
- [#3056](https://github.com/ignite/cli/pull/3056) Add `--genesis-config` flag option to `ignite network chain publish`
- [#2892](https://github.com/ignite/cli/pull/2982/) Add `ignite scaffold react` command.
Expand Down
15 changes: 14 additions & 1 deletion ignite/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
flagYes = "yes"
flagClearCache = "clear-cache"
flagSkipProto = "skip-proto"
flagPlugins = "plugins"

checkVersionTimeout = time.Millisecond * 600
cacheFileName = "ignite_cache.db"
Expand Down Expand Up @@ -81,6 +82,7 @@ To get started, create a blockchain:
c.AddCommand(NewVersion())
c.AddCommand(NewPlugin())
c.AddCommand(deprecated()...)
c.PersistentFlags().AddFlagSet(flagSetPlugins())

return c
}
Expand Down Expand Up @@ -121,7 +123,7 @@ func getHome(cmd *cobra.Command) (home string) {

func flagSetConfig() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.StringP(flagConfig, "c", "", "Ignite config file (default: ./config.yml)")
fs.StringP(flagConfig, "c", "", "path to Ignite config file (default: ./config.yml)")
return fs
}

Expand All @@ -130,6 +132,17 @@ func getConfig(cmd *cobra.Command) (config string) {
return
}

func flagSetPlugins() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.StringP(flagPlugins, "x", "", "path to Ignite plugins config file (default: ./plugins.yml)")
return fs
}

func getPlugins(cmd *cobra.Command) (config string) {
config, _ = cmd.Flags().GetString(flagPlugins)
return
}

func flagSetYes() *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.BoolP(flagYes, "y", false, "answers interactive yes/no questions with yes")
Expand Down
25 changes: 21 additions & 4 deletions ignite/cmd/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"

pluginsconfig "github.com/ignite/cli/ignite/config/plugins"
"github.com/ignite/cli/ignite/pkg/cliui"
"github.com/ignite/cli/ignite/pkg/xgit"
"github.com/ignite/cli/ignite/services/plugin"
Expand All @@ -26,19 +27,35 @@ const (
// LoadPlugins tries to load all the plugins found in configuration.
// If no configuration found, it returns w/o error.
func LoadPlugins(ctx context.Context, rootCmd *cobra.Command) error {
// NOTE(tb) Not sure if it's the right place to load this.
chain, err := newChainWithHomeFlags(rootCmd)
cfg, err := parseLocalPlugins(rootCmd)
tbruyelle marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
// Binary is run outside of an chain app, plugins can't be loaded
// if binary is run where there is no plugins.yml, don't load
return nil
}
plugins, err = plugin.Load(ctx, chain)

// TODO: parse global config
jeronimoalbi marked this conversation as resolved.
Show resolved Hide resolved

plugins, err = plugin.Load(ctx, cfg)
if err != nil {
return err
}
return loadPlugins(rootCmd, plugins)
}

func parseLocalPlugins(rootCmd *cobra.Command) (cfg *pluginsconfig.Config, err error) {
appPath := flagGetPath(rootCmd)
pluginsPath := getPlugins(rootCmd)
if pluginsPath == "" {
if pluginsPath, err = pluginsconfig.LocateDefault(appPath); err != nil {
return cfg, err
}
}

cfg, err = pluginsconfig.ParseFile(pluginsPath)

return cfg, err
}

func loadPlugins(rootCmd *cobra.Command, plugins []*plugin.Plugin) error {
// Link plugins to related commands
var loadErrors []string
Expand Down
6 changes: 3 additions & 3 deletions ignite/cmd/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/ignite/cli/ignite/config"
pluginsconfig "github.com/ignite/cli/ignite/config/plugins"
"github.com/ignite/cli/ignite/services/plugin"
"github.com/ignite/cli/ignite/services/plugin/mocks"
)
Expand Down Expand Up @@ -308,7 +308,7 @@ ignite
assert := assert.New(t)
pi := mocks.NewPluginInterface(t)
p := &plugin.Plugin{
Plugin: config.Plugin{
Plugin: pluginsconfig.Plugin{
Path: "foo",
With: pluginParams,
},
Expand Down Expand Up @@ -537,7 +537,7 @@ func TestLinkPluginHooks(t *testing.T) {
// assert := assert.New(t)
pi := mocks.NewPluginInterface(t)
p := &plugin.Plugin{
Plugin: config.Plugin{
Plugin: pluginsconfig.Plugin{
Path: "foo",
With: pluginParams,
},
Expand Down
24 changes: 0 additions & 24 deletions ignite/config/chain/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,6 @@ type Config struct {
base.Config `yaml:",inline"`

Validators []Validator `yaml:"validators"`
Plugins []Plugin `yaml:"plugins,omitempty"`
}

// Plugin keeps plugin name and location.
type Plugin struct {
// Path holds the location of the plugin.
// A path can be local, in that case it must start with a `/`.
// A remote path on the other hand, is an URL to a public remote git
// repository. For example:
//
// path: github.com/foo/bar
//
// It can contain a path inside that repository, if for instance the repo
// contains multiple plugins, For example:
//
// path: github.com/foo/bar/plugin1
//
// It can also specify a tag or a branch, by adding a `@` and the branch/tag
// name at the end of the path. For example:
//
// 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"`
}

func (c *Config) SetDefaults() error {
Expand Down
9 changes: 0 additions & 9 deletions ignite/config/chain/v1/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,6 @@ func TestConfigDecode(t *testing.T) {
},
},
}},
Plugins: []v1.Plugin{
{
Path: "/path/to/plugin1",
},
{
Path: "/path/to/plugin2",
With: map[string]string{"foo": "bar", "bar": "baz"},
},
},
}
assert.Equal(expected, cfg)
}
Expand Down
76 changes: 76 additions & 0 deletions ignite/config/plugins/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package plugins

import (
"io"
"os"
"path/filepath"

"github.com/imdario/mergo"
"gopkg.in/yaml.v2"
)

// PluginsConfigFilenames is a list of recognized names as Ignite's plugins config file.
var PluginsConfigFilenames = []string{"plugins.yml", "plugins.yaml"}

// DefaultConfig returns a config with default values.
func DefaultConfig() *Config {
c := Config{}
return &c
}

// LocateDefault locates the default path for the config file.
// Returns ErrConfigNotFound when no config file found.
func LocateDefault(root string) (path string, err error) {
for _, name := range PluginsConfigFilenames {
path = filepath.Join(root, name)
if _, err := os.Stat(path); err == nil {
return path, nil
} else if !os.IsNotExist(err) {
return "", err
}
}

return "", ErrConfigNotFound
}

type Config struct {
Plugins []Plugin `yaml:"plugins,omitempty"`
}

// Plugin keeps plugin name and location.
type Plugin struct {
// Path holds the location of the plugin.
// A path can be local, in that case it must start with a `/`.
// A remote path on the other hand, is an URL to a public remote git
// repository. For example:
//
// path: github.com/foo/bar
//
// It can contain a path inside that repository, if for instance the repo
// contains multiple plugins, For example:
//
// path: github.com/foo/bar/plugin1
//
// It can also specify a tag or a branch, by adding a `@` and the branch/tag
// name at the end of the path. For example:
//
// 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"`
}

// Clone returns an identical copy of the instance
func (c *Config) Clone() (*Config, error) {
copy := Config{}
if err := mergo.Merge(&copy, c, mergo.WithAppendSlice); err != nil {
return nil, err
}

return &copy, nil
}

// Decode decodes the config file values from YAML.
func (c *Config) Decode(r io.Reader) error {
return yaml.NewDecoder(r).Decode(c)
}
36 changes: 36 additions & 0 deletions ignite/config/plugins/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package plugins_test

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ignite/cli/ignite/config/plugins"
)

func TestConfigDecode(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
f, err := os.Open("testdata/plugins.yml")
require.NoError(err)
defer f.Close()
var cfg plugins.Config

err = cfg.Decode(f)

require.NoError(err)
expected := plugins.Config{
Plugins: []plugins.Plugin{
{
Path: "/path/to/plugin1",
},
{
Path: "/path/to/plugin2",
With: map[string]string{"foo": "bar", "bar": "baz"},
},
},
}
assert.Equal(expected, cfg)
}
6 changes: 6 additions & 0 deletions ignite/config/plugins/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package plugins

import "errors"

// ErrConfigNotFound indicates that the plugins.yml can't be found.
var ErrConfigNotFound = errors.New("could not locate a plugins.yml")
33 changes: 33 additions & 0 deletions ignite/config/plugins/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package plugins

import (
"io"
"os"

"gopkg.in/yaml.v2"
)

// ParseFile parses a plugins config.
func ParseFile(path string) (*Config, error) {
file, err := os.Open(path)
if err != nil {
return DefaultConfig(), err
}

defer file.Close()

return Parse(file)
}

// Parse reads a config file for ignite binary plugins
func Parse(configFile io.Reader) (*Config, error) {
return parse(configFile)
}

func parse(configFile io.Reader) (*Config, error) {
var c Config

err := yaml.NewDecoder(configFile).Decode(&c)

return &c, err
}
25 changes: 25 additions & 0 deletions ignite/config/plugins/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package plugins_test

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"

pluginsconfig "github.com/ignite/cli/ignite/config/plugins"
"github.com/ignite/cli/ignite/config/plugins/testdata"
)

func TestParse(t *testing.T) {
// Arrange: Initialize a reader with the previous version
r := bytes.NewReader(testdata.ConfigYAML)

// Act
cfg, err := pluginsconfig.Parse(r)

// Assert
require.NoError(t, err)

// Assert: Parse must return the latest version
require.Equal(t, testdata.GetConfig(t), cfg)
}
8 changes: 8 additions & 0 deletions ignite/config/plugins/testdata/plugins.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins:
- name: plugin1
path: /path/to/plugin1
- name: plugin2
path: /path/to/plugin2
with:
foo: bar
bar: baz
24 changes: 24 additions & 0 deletions ignite/config/plugins/testdata/testdata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package testdata

import (
"bytes"
_ "embed"
"testing"

"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"

pluginsconfig "github.com/ignite/cli/ignite/config/plugins"
)

//go:embed plugins.yml
var ConfigYAML []byte

func GetConfig(t *testing.T) *pluginsconfig.Config {
c := &pluginsconfig.Config{}

err := yaml.NewDecoder(bytes.NewReader(ConfigYAML)).Decode(c)
require.NoError(t, err)

return c
}
6 changes: 0 additions & 6 deletions ignite/config/pluginsconfig.go

This file was deleted.

Loading