Skip to content

Commit

Permalink
refactor: Add basic GetChainInfo method to plugin API (#3561)
Browse files Browse the repository at this point in the history
* refactor: Analyzer/analizer -> ClientAPI

* refactor: rename proto files and rebuild

* refactor: Add json tags

* wip/refactor: Module analysis

* feat: Add chain reference to plugin ClientAPI

* feat: Complete Dependencies ClientAPI method

* fix: Address review comments

* feat: Remove services/chain dep from pkg/cosmosanalysis as per discussion

* wip: remove deptools install

* feat: package-specific includes

* fix: Replace Module List call with Chain Info call

* chore: Remove chain analysis code

* feat: ChainInfo API example template

* chore: Update template cli reference

* chore: clean up PR

* fix: Address review comments

* fix: address review comments

* fix: address review comments

* fix: Tests and linting

* chore: add changelog

* fix: linting issues

* tests: fix issue with client api in plugin tests

* tests: fix plugin template for integration tests

---------

Co-authored-by: jeronimoalbi <[email protected]>
  • Loading branch information
clockworkgr and jeronimoalbi committed Sep 5, 2023
1 parent 00d5330 commit d3918a7
Show file tree
Hide file tree
Showing 35 changed files with 800 additions and 1,781 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Features

- [#3544](https://github.com/ignite/cli/pull/3544) Add bidirectional communication to plugin system
- [#3561](https://github.com/ignite/cli/pull/3561) Add GetChainInfo method to plugin system API

### Changes

Expand Down
24 changes: 12 additions & 12 deletions docs/docs/plugins/02-dev-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,30 @@ type Interface interface {
// Execute will be invoked by ignite when a plugin Command is executed.
// It is global for all commands declared in Manifest, if you have declared
// multiple commands, use cmd.Path to distinguish them.
// The analizer argument can be used by plugins to get chain app analysis info.
Execute(context.Context, *ExecutedCommand, Analyzer) error
// The ClientAPI argument can be used by plugins to get chain app analysis info.
Execute(context.Context, *ExecutedCommand, ClientAPI) error

// ExecuteHookPre is invoked by ignite when a command specified by the Hook
// path is invoked.
// It is global for all hooks declared in Manifest, if you have declared
// multiple hooks, use hook.Name to distinguish them.
// The analizer argument can be used by plugins to get chain app analysis info.
ExecuteHookPre(context.Context, *ExecutedHook, Analyzer) error
// The ClientAPI argument can be used by plugins to get chain app analysis info.
ExecuteHookPre(context.Context, *ExecutedHook, ClientAPI) error

// ExecuteHookPost is invoked by ignite when a command specified by the hook
// path is invoked.
// It is global for all hooks declared in Manifest, if you have declared
// multiple hooks, use hook.Name to distinguish them.
// The analizer argument can be used by plugins to get chain app analysis info.
ExecuteHookPost(context.Context, *ExecutedHook, Analyzer) error
// The ClientAPI argument can be used by plugins to get chain app analysis info.
ExecuteHookPost(context.Context, *ExecutedHook, ClientAPI) error

// ExecuteHookCleanUp is invoked by ignite when a command specified by the
// hook path is invoked. Unlike ExecuteHookPost, it is invoked regardless of
// execution status of the command and hooks.
// It is global for all hooks declared in Manifest, if you have declared
// multiple hooks, use hook.Name to distinguish them.
// The analizer argument can be used by plugins to get chain app analysis info.
ExecuteHookCleanUp(context.Context, *ExecutedHook, Analyzer) error
// The ClientAPI argument can be used by plugins to get chain app analysis info.
ExecuteHookCleanUp(context.Context, *ExecutedHook, ClientAPI) error
}
```

Expand Down Expand Up @@ -160,7 +160,7 @@ To update the plugin execution, you have to change the plugin `Execute` command,
for instance :

```go
func (p) Execute(_ context.Context, cmd *plugin.ExecutedCommand, _ plugin.Analyzer) error {
func (p) Execute(_ context.Context, cmd *plugin.ExecutedCommand, _ plugin.ClientAPI) error {
if len(cmd.Args) == 0 {
return fmt.Errorf("oracle name missing")
}
Expand Down Expand Up @@ -221,7 +221,7 @@ func (p) Manifest(context.Context) (*plugin.Manifest, error) {
}, nil
}

func (p) ExecuteHookPre(_ context.Context, h *plugin.ExecutedHook, _ plugin.Analyzer) error {
func (p) ExecuteHookPre(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error {
switch h.Hook.GetName() {
case "my-hook":
fmt.Println("I'm executed before ignite chain build")
Expand All @@ -231,7 +231,7 @@ func (p) ExecuteHookPre(_ context.Context, h *plugin.ExecutedHook, _ plugin.Anal
return nil
}

func (p) ExecuteHookPost(_ context.Context, h *plugin.ExecutedHook, _ plugin.Analyzer) error {
func (p) ExecuteHookPost(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error {
switch h.Hook.GetName() {
case "my-hook":
fmt.Println("I'm executed after ignite chain build (if no error)")
Expand All @@ -241,7 +241,7 @@ func (p) ExecuteHookPost(_ context.Context, h *plugin.ExecutedHook, _ plugin.Ana
return nil
}

func (p) ExecuteHookCleanUp(_ context.Context, h *plugin.ExecutedHook, _ plugin.Analyzer) error {
func (p) ExecuteHookCleanUp(_ context.Context, h *plugin.ExecutedHook, _ plugin.ClientAPI) error {
switch h.Hook.GetName() {
case "my-hook":
fmt.Println("I'm executed after ignite chain build (regardless errors)")
Expand Down
30 changes: 25 additions & 5 deletions ignite/cmd/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,11 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook *plugin.Hook)
}

execHook := newExecutedHook(hook, cmd, args)
err := p.Interface.ExecuteHookPre(ctx, execHook, plugin.NewAnalyzer())
c, err := newChainWithHomeFlags(cmd)
if err != nil {
return err
}
err = p.Interface.ExecuteHookPre(ctx, execHook, plugin.NewClientAPI(c))
if err != nil {
return fmt.Errorf("plugin %q ExecuteHookPre() error: %w", p.Path, err)
}
Expand All @@ -223,7 +227,11 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook *plugin.Hook)
if err != nil {
ctx := cmd.Context()
execHook := newExecutedHook(hook, cmd, args)
err := p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewAnalyzer())
c, err := newChainWithHomeFlags(cmd)
if err != nil {
return err
}
err = p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewClientAPI(c))
if err != nil {
fmt.Printf("plugin %q ExecuteHookCleanUp() error: %v", p.Path, err)
}
Expand All @@ -240,8 +248,12 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook *plugin.Hook)
ctx := cmd.Context()
execHook := newExecutedHook(hook, cmd, args)

c, err := newChainWithHomeFlags(cmd)
if err != nil {
return err
}
defer func() {
err := p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewAnalyzer())
err := p.Interface.ExecuteHookCleanUp(ctx, execHook, plugin.NewClientAPI(c))
if err != nil {
fmt.Printf("plugin %q ExecuteHookCleanUp() error: %v", p.Path, err)
}
Expand All @@ -255,7 +267,11 @@ func linkPluginHook(rootCmd *cobra.Command, p *plugin.Plugin, hook *plugin.Hook)
}
}

err := p.Interface.ExecuteHookPost(ctx, execHook, plugin.NewAnalyzer())
c, err = newChainWithHomeFlags(cmd)
if err != nil {
return err
}
err = p.Interface.ExecuteHookPost(ctx, execHook, plugin.NewClientAPI(c))
if err != nil {
return fmt.Errorf("plugin %q ExecuteHookPost() error : %w", p.Path, err)
}
Expand Down Expand Up @@ -327,7 +343,11 @@ func linkPluginCmd(rootCmd *cobra.Command, p *plugin.Plugin, pluginCmd *plugin.C
}
execCmd.ImportFlags(cmd)
// Call the plugin Execute
err := p.Interface.Execute(ctx, execCmd, plugin.NewAnalyzer())
c, err := newChainWithHomeFlags(cmd)
if err != nil {
return err
}
err = p.Interface.Execute(ctx, execCmd, plugin.NewClientAPI(c))
// NOTE(tb): This pause gives enough time for go-plugin to sync the
// output from stdout/stderr of the plugin. Without that pause, this
// output can be discarded and not printed in the user console.
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 @@ -97,7 +97,7 @@ func TestLinkPluginCmds(t *testing.T) {
}),
mock.Anything,
).
Run(func(_ context.Context, execCmd *plugin.ExecutedCommand, _ plugin.Analyzer) {
Run(func(_ context.Context, execCmd *plugin.ExecutedCommand, _ plugin.ClientAPI) {
// Assert execCmd is populated correctly
assert.True(t, strings.HasSuffix(execCmd.Path, cmd.Use), "wrong path %s", execCmd.Path)
assert.Equal(t, args, execCmd.Args)
Expand Down Expand Up @@ -419,8 +419,8 @@ func TestLinkPluginHooks(t *testing.T) {
hook.PlaceHookOn == execHook.Hook.PlaceHookOn
})
}
asserter := func(hook *plugin.Hook) func(_ context.Context, hook *plugin.ExecutedHook, _ plugin.Analyzer) {
return func(_ context.Context, execHook *plugin.ExecutedHook, _ plugin.Analyzer) {
asserter := func(hook *plugin.Hook) func(_ context.Context, hook *plugin.ExecutedHook, _ plugin.ClientAPI) {
return func(_ context.Context, execHook *plugin.ExecutedHook, _ plugin.ClientAPI) {
assert.True(t, strings.HasSuffix(execHook.ExecutedCommand.Path, hook.PlaceHookOn), "wrong path %q want %q", execHook.ExecutedCommand.Path, hook.PlaceHookOn)
assert.Equal(t, args, execHook.ExecutedCommand.Args)
assertFlags(t, expectedFlags, execHook.ExecutedCommand)
Expand Down
35 changes: 18 additions & 17 deletions ignite/pkg/cosmosanalysis/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,58 @@ type Msgs map[string][]string
// Module keeps metadata about a Cosmos SDK module.
type Module struct {
// Name of the module.
Name string
Name string `json:"name,omitempty"`

// GoModulePath of the app where the module is defined.
GoModulePath string
GoModulePath string `json:"go_module_path,omitempty"`

// Pkg holds the proto package info.
Pkg protoanalysis.Package
Pkg protoanalysis.Package `json:"package,omitempty"`

// Msg is a list of sdk.Msg implementation of the module.
Msgs []Msg
Msgs []Msg `json:"messages,omitempty"`

// HTTPQueries is a list of module queries.
HTTPQueries []HTTPQuery
HTTPQueries []HTTPQuery `json:"http_queries,omitempty"`

// Types is a list of proto types that might be used by module.
Types []Type
Types []Type `json:"types,omitempty"`
}

// Msg keeps metadata about an sdk.Msg implementation.
type Msg struct {
// Name of the type.
Name string
Name string `json:"name,omitempty"`

// URI of the type.
URI string
URI string `json:"uri,omitempty"`

// FilePath is the path of the .proto file where message is defined at.
FilePath string
// File path is the path of the proto file where message is defined.
FilePath string `json:"file_path,omitempty"`
}

// HTTPQuery is an sdk Query.
type HTTPQuery struct {
// Name of the RPC func.
Name string
Name string `json:"name,omitempty"`

// FullName of the query with service name and rpc func name.
FullName string
FullName string `json:"full_name,omitempty"`

// HTTPAnnotations keeps info about http annotations of query.
Rules []protoanalysis.HTTPRule
Rules []protoanalysis.HTTPRule `json:"rules,omitempty"`

// Paginated indicates that the query is using pagination.
Paginated bool
Paginated bool `json:"paginated,omitempty"`
}

// Type is a proto type that might be used by module.
type Type struct {
Name string
// Name pf the type.
Name string `json:"name,omitempty"`

// FilePath is the path of the .proto file where message is defined at.
FilePath string
// File path is the path of the .proto file where message is defined at.
FilePath string `json:"file_path,omitempty"`
}

type moduleDiscoverer struct {
Expand Down
2 changes: 1 addition & 1 deletion ignite/pkg/cosmosclient/mocks/account_retriever.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ignite/pkg/cosmosclient/mocks/bank_query_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions ignite/pkg/cosmosclient/mocks/faucet_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 11 additions & 3 deletions ignite/pkg/cosmosclient/mocks/gasometer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ignite/pkg/cosmosclient/mocks/rpc_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion ignite/pkg/cosmosclient/mocks/signer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ignite/pkg/cosmosgen/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (g *generator) setup() (err error) {
}

// Read the dependencies defined in the `go.mod` file
g.deps, err = gomodule.ResolveDependencies(modFile)
g.deps, err = gomodule.ResolveDependencies(modFile, false)
if err != nil {
return err
}
Expand Down
10 changes: 7 additions & 3 deletions ignite/pkg/cosmostxcollector/mocks/saver.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d3918a7

Please sign in to comment.