From 4f93cdb2af2e1665693dd120aa5ac3034a290218 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Tue, 28 Nov 2023 16:41:15 +0100 Subject: [PATCH 01/17] fix: restore runtime app API registered modules --- ignite/pkg/cosmosanalysis/app/app.go | 268 ++++++++++++++++++++++----- 1 file changed, 221 insertions(+), 47 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 41f284e4e2..53552aed7b 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -1,19 +1,25 @@ package app import ( + "errors" "fmt" "go/ast" "go/parser" "go/token" + "os" "path/filepath" "strings" + "github.com/ignite/cli/ignite/pkg/cosmosanalysis" + "github.com/ignite/cli/ignite/pkg/cosmosver" "github.com/ignite/cli/ignite/pkg/goanalysis" + "github.com/ignite/cli/ignite/pkg/goenv" + "github.com/ignite/cli/ignite/pkg/gomodule" "github.com/ignite/cli/ignite/pkg/xast" - - "github.com/ignite/cli/ignite/pkg/cosmosanalysis" ) +const registerRoutesMethod = "RegisterAPIRoutes" + // CheckKeeper checks for the existence of the keeper with the provided name in the app structure. func CheckKeeper(path, keeperName string) error { // find app type @@ -85,12 +91,11 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { } // Loop on package's files - var blankImports []string - var discovered []string + var blankImports, discovered []string for _, f := range appPkg.Files { blankImports = append(blankImports, goanalysis.FindBlankImports(f)...) fileImports := goanalysis.FormatImports(f) - d, err := FindKeepersModules(f, fileImports) + d, err := DiscoverModules(f, chainRoot, fileImports) if err != nil { return nil, err } @@ -132,8 +137,8 @@ func mergeImports(blankImports, discovered []string) []string { return imports } -// FindKeepersModules find a map of import modules based on the keepers params on the App struct. -func FindKeepersModules(n ast.Node, fileImports map[string]string) ([]string, error) { +// DiscoverModules find a map of import modules based on the configured app. +func DiscoverModules(n ast.Node, chainRoot string, fileImports map[string]string) ([]string, error) { // find app type appImpl := cosmosanalysis.FindImplementationInFile(n, cosmosanalysis.AppImplementation) appTypeName := "App" @@ -149,58 +154,190 @@ func FindKeepersModules(n ast.Node, fileImports map[string]string) ([]string, er return nil, nil } - keeperParamsMap := make(map[string]struct{}) + var discovered []string for _, decl := range file.Decls { - genDecl, ok := decl.(*ast.GenDecl) + switch x := decl.(type) { + case *ast.GenDecl: + discovered = append(discovered, discoverKeeperModules(x, appTypeName, fileImports)...) + case *ast.FuncDecl: + // The modules registered by Cosmos SDK `rumtime.App` are included + // when the app registers API modules though the `App` instance. + if isRuntimeAppCalled(x) { + m, err := discoverRuntimeAppModules(x, chainRoot) + if err != nil { + return nil, err + } + discovered = append(discovered, m...) + } + } + } + + // Add discovered modules to a list without duplicates + var ( + modules []string + skip = make(map[string]struct{}) + ) + for _, name := range discovered { + if _, ok := skip[name]; ok { + continue + } + + skip[name] = struct{}{} + modules = append(modules, name) + } + return modules, nil +} + +func discoverKeeperModules(d *ast.GenDecl, appTypeName string, imports map[string]string) []string { + var modules []string + for _, spec := range d.Specs { + typeSpec, ok := spec.(*ast.TypeSpec) if !ok { continue } - for _, spec := range genDecl.Specs { - typeSpec, ok := spec.(*ast.TypeSpec) - if !ok { - continue - } - if typeSpec.Name.Name != appTypeName { - continue - } - structType, ok := typeSpec.Type.(*ast.StructType) - if !ok { - continue + if typeSpec.Name.Name != appTypeName { + continue + } + structType, ok := typeSpec.Type.(*ast.StructType) + if !ok { + continue + } + for _, field := range structType.Fields.List { + f := field.Type + CheckSpec: + switch spec := f.(type) { + case *ast.StarExpr: + f, ok = spec.X.(*ast.SelectorExpr) + if !ok { + continue + } + goto CheckSpec + case *ast.SelectorExpr: + if !strings.HasSuffix(spec.Sel.Name, "Keeper") { + continue + } + ident, ok := spec.X.(*ast.Ident) + if !ok { + continue + } + fileImport, ok := imports[ident.Name] + if !ok { + continue + } + modules = append(modules, removeKeeperPkgPath(fileImport)) } - for _, field := range structType.Fields.List { - f := field.Type - CheckSpec: - switch spec := f.(type) { - case *ast.StarExpr: - f, ok = spec.X.(*ast.SelectorExpr) - if !ok { - continue - } - goto CheckSpec - case *ast.SelectorExpr: - if !strings.HasSuffix(spec.Sel.Name, "Keeper") { - continue - } - ident, ok := spec.X.(*ast.Ident) - if !ok { - continue - } - fileImport, ok := fileImports[ident.Name] - if !ok { - continue - } - keeperParamsMap[removeKeeperPkgPath(fileImport)] = struct{}{} + } + } + return modules +} + +func discoverRuntimeAppModules(fn *ast.FuncDecl, chainRoot string) ([]string, error) { + // Resolve the absolute path to the Cosmos SDK module + cosmosPath, err := resolveCosmosPackagePath(chainRoot) + if err != nil { + return nil, err + } + + var modules []string + + // When runtime package doesn't exists it means is an older Cosmos SDK version, + // so all the module API registrations are defined within user's app. + path := filepath.Join(cosmosPath, "runtime", "app.go") + if _, err := os.Stat(path); os.IsNotExist(err) { + return modules, nil + } + + f, _, err := xast.ParseFile(path) + if err != nil { + return nil, err + } + + imports := goanalysis.FormatImports(f) + err = xast.Inspect(f, func(n ast.Node) error { + if pkgs := findRegisterAPIRoutesRegistrations(n); pkgs != nil { + for _, p := range pkgs { + if m := imports[p]; m != "" { + modules = append(modules, m) } } + return xast.ErrStop + } + return nil + }) + + if err != nil { + return nil, err + } + return modules, nil +} + +func resolveCosmosPackagePath(chainRoot string) (string, error) { + modFile, err := gomodule.ParseAt(chainRoot) + if err != nil { + return "", err + } + + deps, err := gomodule.ResolveDependencies(modFile, false) + if err != nil { + return "", err + } + + var pkg string + for _, dep := range deps { + if dep.Path == cosmosver.CosmosModulePath { + pkg = dep.String() + break } } - keeperParams := make([]string, 0) - for param := range keeperParamsMap { - keeperParams = append(keeperParams, param) + if pkg == "" { + return "", errors.New("Cosmos SDK package version not found") } - return keeperParams, nil + // Check path of the package directory within Go's module cache + path := filepath.Join(goenv.GoModCache(), pkg) + info, err := os.Stat(path) + if os.IsNotExist(err) || !info.IsDir() { + return "", errors.New("local path to Cosmos SDK package not found") + } + return path, nil +} + +func findRegisterAPIRoutesRegistrations(n ast.Node) []string { + funcLitType, ok := n.(*ast.FuncDecl) + if !ok { + return nil + } + + if funcLitType.Name.Name != registerRoutesMethod { + return nil + } + + var packagesRegistered []string + for _, stmt := range funcLitType.Body.List { + exprStmt, ok := stmt.(*ast.ExprStmt) + if !ok { + continue + } + exprCall, ok := exprStmt.X.(*ast.CallExpr) + if !ok { + continue + } + exprFun, ok := exprCall.Fun.(*ast.SelectorExpr) + if !ok || exprFun.Sel.Name != "RegisterGRPCGatewayRoutes" { + continue + } + identType, ok := exprFun.X.(*ast.Ident) + if !ok { + continue + } + pkgName := identType.Name + if pkgName == "" { + continue + } + packagesRegistered = append(packagesRegistered, identType.Name) + } + return packagesRegistered } func removeKeeperPkgPath(pkg string) string { @@ -208,3 +345,40 @@ func removeKeeperPkgPath(pkg string) string { path = strings.TrimSuffix(path, "/controller") return strings.TrimSuffix(path, "/host") } + +func isRuntimeAppCalled(fn *ast.FuncDecl) bool { + if fn.Name.Name != registerRoutesMethod { + return false + } + + for _, stmt := range fn.Body.List { + exprStmt, ok := stmt.(*ast.ExprStmt) + if !ok { + continue + } + + exprCall, ok := exprStmt.X.(*ast.CallExpr) + if !ok { + continue + } + + exprFun, ok := exprCall.Fun.(*ast.SelectorExpr) + if !ok || exprFun.Sel.Name != registerRoutesMethod { + continue + } + + exprSel, ok := exprFun.X.(*ast.SelectorExpr) + if !ok || exprSel.Sel.Name != "App" { + continue + } + + identType, ok := exprSel.X.(*ast.Ident) + if !ok || identType.Name != "app" { + continue + } + + return true + } + + return false +} From 44dd09b3734cad96cd57194ad4876309836244b8 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Tue, 28 Nov 2023 16:53:14 +0100 Subject: [PATCH 02/17] ci: fix lint issue with unused argument --- ignite/pkg/cosmosanalysis/app/app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 53552aed7b..fdd5a76477 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -163,7 +163,7 @@ func DiscoverModules(n ast.Node, chainRoot string, fileImports map[string]string // The modules registered by Cosmos SDK `rumtime.App` are included // when the app registers API modules though the `App` instance. if isRuntimeAppCalled(x) { - m, err := discoverRuntimeAppModules(x, chainRoot) + m, err := discoverRuntimeAppModules(chainRoot) if err != nil { return nil, err } @@ -231,7 +231,7 @@ func discoverKeeperModules(d *ast.GenDecl, appTypeName string, imports map[strin return modules } -func discoverRuntimeAppModules(fn *ast.FuncDecl, chainRoot string) ([]string, error) { +func discoverRuntimeAppModules(chainRoot string) ([]string, error) { // Resolve the absolute path to the Cosmos SDK module cosmosPath, err := resolveCosmosPackagePath(chainRoot) if err != nil { From a5ce7187e193e04338807d72ae43d30d2d8da7da Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Tue, 28 Nov 2023 17:51:50 +0100 Subject: [PATCH 03/17] tests: fix broken unit tests --- ignite/pkg/cosmosanalysis/app/app_test.go | 18 ++++++++-- .../app/testdata/modules/app_config/go.mod | 30 +++++++++++++++++ .../app/testdata/modules/crescent/app.go | 11 ------- .../app/testdata/modules/crescent/go.mod | 29 ++++++++++++++++ .../app/testdata/modules/gaia/app.go | 12 ------- .../app/testdata/modules/gaia/go.mod | 28 ++++++++++++++++ .../app/testdata/modules/juno/go.mod | 33 +++++++++++++++++++ .../app/testdata/modules/single_app/go.mod | 32 ++++++++++++++++++ .../app/testdata/modules/spn/go.mod | 32 ++++++++++++++++++ 9 files changed, 200 insertions(+), 25 deletions(-) create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod create mode 100644 ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod diff --git a/ignite/pkg/cosmosanalysis/app/app_test.go b/ignite/pkg/cosmosanalysis/app/app_test.go index 35545e3959..07ee898f61 100644 --- a/ignite/pkg/cosmosanalysis/app/app_test.go +++ b/ignite/pkg/cosmosanalysis/app/app_test.go @@ -85,6 +85,9 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/staking", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", } cases := []struct { @@ -125,6 +128,8 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/ignite/mars/x/mars", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, { @@ -239,6 +244,9 @@ func TestFindRegisteredModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/authz", "github.com/CosmWasm/wasmd/x/wasm", "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, } @@ -252,13 +260,16 @@ func TestFindRegisteredModules(t *testing.T) { } } -func TestFindKeepersModules(t *testing.T) { +func TestDiscoverModules(t *testing.T) { basicModules := []string{ "github.com/cosmos/cosmos-sdk/x/auth", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/staking", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/username/test/x/foo", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", } cases := []struct { @@ -391,6 +402,9 @@ func TestFindKeepersModules(t *testing.T) { "github.com/cosmos/cosmos-sdk/x/authz", "github.com/CosmWasm/wasmd/x/wasm", "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", }, }, } @@ -403,7 +417,7 @@ func TestFindKeepersModules(t *testing.T) { got := make([]string, 0) for _, f := range appPkg.Files { fileImports := goanalysis.FormatImports(f) - modules, err := FindKeepersModules(f, fileImports) + modules, err := DiscoverModules(f, tt.path, fileImports) require.NoError(t, err) if modules != nil { got = append(got, modules...) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod new file mode 100644 index 0000000000..c740bc6ccb --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/app_config/go.mod @@ -0,0 +1,30 @@ +module app + +go 1.20 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/core v0.5.1 + cosmossdk.io/depinject v1.0.0-alpha.3 + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.1 + github.com/bufbuild/buf v1.23.1 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go index 17455318e7..a01d492c2a 100644 --- a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/app.go @@ -11,7 +11,6 @@ import ( "path/filepath" storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/server" "cosmossdk.io/client/v2/autocli" "github.com/gorilla/mux" @@ -1031,13 +1030,3 @@ func (App) GetSubspace(moduleName string) paramstypes.Subspace { func (App) SimulationManager() *module.SimulationManager { return app.sm } - -// RegisterAPIRoutes registers all application module routes with the provided -// API server. -func (App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { - app.App.RegisterAPIRoutes(apiSvr, apiConfig) - // register swagger API in app.go so that other applications can override easily - if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { - panic(err) - } -} diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod new file mode 100644 index 0000000000..d0b47f88a3 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/crescent/go.mod @@ -0,0 +1,29 @@ +module github.com/crescent-network/crescent/v5 + +go 1.18 + +require ( + github.com/cosmos/cosmos-sdk v0.45.10 + github.com/cosmos/ibc-go/v3 v3.4.0 + github.com/gogo/protobuf v1.3.3 + github.com/golang/mock v1.6.0 + github.com/golang/protobuf v1.5.2 + github.com/golangci/golangci-lint v1.50.1 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.13.0 + github.com/rakyll/statik v0.1.7 + github.com/regen-network/cosmos-proto v0.3.1 + github.com/spf13/cast v1.5.0 + github.com/spf13/cobra v1.6.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.0 + github.com/tendermint/tendermint v0.34.22 + github.com/tendermint/tm-db v0.6.7 + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e + google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c + google.golang.org/grpc v1.50.1 + google.golang.org/protobuf v1.28.1 + gopkg.in/yaml.v2 v2.4.0 +) + diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go index 27ee658340..e9c475528d 100644 --- a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/app.go @@ -8,8 +8,6 @@ import ( "os" "path/filepath" - "github.com/cosmos/cosmos-sdk/server" - "cosmossdk.io/client/v2/autocli" sdkerrors "cosmossdk.io/errors" "github.com/cosmos/cosmos-sdk/baseapp" @@ -1096,13 +1094,3 @@ func (GaiaApp) GetSubspace(moduleName string) paramstypes.Subspace { func (GaiaApp) SimulationManager() *module.SimulationManager { return app.sm } - -// RegisterAPIRoutes registers all application module routes with the provided -// API server. -func (GaiaApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { - app.App.RegisterAPIRoutes(apiSvr, apiConfig) - // register swagger API in app.go so that other applications can override easily - if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { - panic(err) - } -} diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod new file mode 100644 index 0000000000..0851601f21 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/gaia/go.mod @@ -0,0 +1,28 @@ +module github.com/cosmos/gaia/v14 + +go 1.20 + +require ( + cosmossdk.io/errors v1.0.0 + cosmossdk.io/math v1.2.0 + github.com/cosmos/cosmos-sdk v0.45.16 + github.com/cosmos/go-bip39 v1.0.0 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v4 v4.1.1 + github.com/cosmos/ibc-go/v4 v4.4.2 + github.com/cosmos/interchain-security/v2 v2.0.0 + github.com/gogo/protobuf v1.3.3 + github.com/golang/protobuf v1.5.3 + github.com/google/gofuzz v1.2.0 + github.com/gorilla/mux v1.8.1 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/ory/dockertest/v3 v3.10.0 + github.com/rakyll/statik v0.1.7 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.17.0 + github.com/stretchr/testify v1.8.4 + github.com/tendermint/tendermint v0.34.27 + github.com/tendermint/tm-db v0.6.7 + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb + google.golang.org/grpc v1.58.2 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod new file mode 100644 index 0000000000..c3c0312603 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/juno/go.mod @@ -0,0 +1,33 @@ +module github.com/CosmosContracts/juno/v18 + +go 1.21 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/errors v1.0.0 + cosmossdk.io/log v1.2.1 + cosmossdk.io/math v1.1.2 + cosmossdk.io/tools/rosetta v0.2.1 + github.com/CosmWasm/wasmd v0.45.0 + github.com/CosmWasm/wasmvm v1.5.0 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-sdk v0.47.5 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.0.1 + github.com/cosmos/ibc-apps/modules/async-icq/v7 v7.0.0 + github.com/cosmos/ibc-apps/modules/ibc-hooks/v7 v7.0.0-20230803181732-7c8f814d3b79 + github.com/cosmos/ibc-go/v7 v7.3.1 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/prometheus/client_golang v1.16.0 + github.com/skip-mev/pob v1.0.4 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/viper v1.16.0 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 + google.golang.org/grpc v1.58.3 + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod new file mode 100644 index 0000000000..5db6c247a4 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/single_app/go.mod @@ -0,0 +1,32 @@ +module app + +go 1.20 + +require ( + cosmossdk.io/api v0.3.1 + cosmossdk.io/core v0.5.1 + cosmossdk.io/depinject v1.0.0-alpha.3 + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.1 + github.com/bufbuild/buf v1.23.1 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/golang/protobuf v1.5.3 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 +) + + diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod new file mode 100644 index 0000000000..46b9f1988b --- /dev/null +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod @@ -0,0 +1,32 @@ +module github.com/tendermint/spn + +go 1.19 + +require ( + cosmossdk.io/errors v1.0.0-beta.7 + cosmossdk.io/math v1.0.0-beta.4 + github.com/aws/smithy-go v1.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.1 + github.com/cosmos/cosmos-sdk v0.46.7 + github.com/cosmos/ibc-go/v6 v6.0.0 + github.com/gogo/protobuf v1.3.3 + github.com/golang/protobuf v1.5.2 + github.com/golangci/golangci-lint v1.50.1 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/ignite/modules v0.0.0-20221215224430-496fd9a7820c + github.com/pkg/errors v0.9.1 + github.com/spf13/cast v1.5.0 + github.com/spf13/cobra v1.6.1 + github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.1 + github.com/tendermint/fundraising v0.3.1 + github.com/tendermint/tendermint v0.34.24 + github.com/tendermint/tm-db v0.6.7 + golang.org/x/tools v0.2.0 + google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 + google.golang.org/grpc v1.50.1 + google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 + gopkg.in/yaml.v2 v2.4.0 + mvdan.cc/gofumpt v0.4.0 +) From 46ee7bca15aaa048001bd88d70b9d8d5c2015053 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Tue, 28 Nov 2023 17:55:58 +0100 Subject: [PATCH 04/17] ci: fix linting issue --- ignite/pkg/cosmosanalysis/app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index fdd5a76477..0d0f3b63f8 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -291,7 +291,7 @@ func resolveCosmosPackagePath(chainRoot string) (string, error) { } if pkg == "" { - return "", errors.New("Cosmos SDK package version not found") + return "", errors.New("cosmos SDK package version not found") } // Check path of the package directory within Go's module cache From d54daf8bae8528d8c49686b277e2c489541c74cc Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Thu, 30 Nov 2023 15:36:03 +0100 Subject: [PATCH 05/17] feat: add support for IBC modules discovery This is a temporary feature that should be removed once IBC modules are injected inteas of being wired using the definitions from the scafolded app file `app/ibc.go`. --- ignite/pkg/cosmosanalysis/app/app.go | 80 +++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 0d0f3b63f8..46adbea711 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -101,6 +101,19 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { } discovered = append(discovered, d...) } + + // Discover IBC wired modules + // TODO: This can be removed once IBC modules use dependency injection + ibcPath := filepath.Join(chainRoot, "app", "ibc.go") + if _, err := os.Stat(ibcPath); err == nil { + m, err := discoverIBCModules(ibcPath) + if err != nil { + return nil, err + } + + discovered = append(discovered, m...) + } + return mergeImports(blankImports, discovered), nil } @@ -138,9 +151,9 @@ func mergeImports(blankImports, discovered []string) []string { } // DiscoverModules find a map of import modules based on the configured app. -func DiscoverModules(n ast.Node, chainRoot string, fileImports map[string]string) ([]string, error) { +func DiscoverModules(file *ast.File, chainRoot string, fileImports map[string]string) ([]string, error) { // find app type - appImpl := cosmosanalysis.FindImplementationInFile(n, cosmosanalysis.AppImplementation) + appImpl := cosmosanalysis.FindImplementationInFile(file, cosmosanalysis.AppImplementation) appTypeName := "App" switch { case len(appImpl) > 1: @@ -149,11 +162,6 @@ func DiscoverModules(n ast.Node, chainRoot string, fileImports map[string]string appTypeName = appImpl[0] } - file, ok := n.(*ast.File) - if !ok { - return nil, nil - } - var discovered []string for _, decl := range file.Decls { switch x := decl.(type) { @@ -271,6 +279,64 @@ func discoverRuntimeAppModules(chainRoot string) ([]string, error) { return modules, nil } +func discoverIBCModules(ibcPath string) ([]string, error) { + f, _, err := xast.ParseFile(ibcPath) + if err != nil { + return nil, err + } + + var ( + names []string + imports = goanalysis.FormatImports(f) + ) + err = xast.Inspect(f, func(n ast.Node) error { + fn, _ := n.(*ast.FuncDecl) + if fn == nil { + return nil + } + + if fn.Name.Name != "AddIBCModuleManager" { + return nil + } + + for _, stmt := range fn.Body.List { + x, _ := stmt.(*ast.AssignStmt) + if x == nil { + continue + } + + if len(x.Rhs) == 0 { + continue + } + + c, _ := x.Rhs[0].(*ast.CompositeLit) + if c == nil { + continue + } + + s, _ := c.Type.(*ast.SelectorExpr) + if s == nil || s.Sel.Name != "AppModule" { + continue + } + + if m, _ := s.X.(*ast.Ident); m != nil { + names = append(names, m.Name) + } + } + + return xast.ErrStop + }) + if err != nil { + return nil, err + } + + var modules []string + for _, n := range names { + modules = append(modules, imports[n]) + } + return modules, nil +} + func resolveCosmosPackagePath(chainRoot string) (string, error) { modFile, err := gomodule.ParseAt(chainRoot) if err != nil { From d9d7c3579835b2de322ad093d65a23cb9144e0c4 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Thu, 30 Nov 2023 15:54:06 +0100 Subject: [PATCH 06/17] fix: correct issue that cause modules not to be discovered The removed snippet was not able to handle some Go import paths which were removed, like the IBC ones, also causing that the TS client generation was incomplete because of the missing modules. --- ignite/pkg/cosmosanalysis/app/app.go | 50 +++++++++------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 46adbea711..a1a6bb6c99 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -90,10 +90,10 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { return nil, err } - // Loop on package's files - var blankImports, discovered []string + // Search the app for the imported SDK modules + var discovered []string for _, f := range appPkg.Files { - blankImports = append(blankImports, goanalysis.FindBlankImports(f)...) + discovered = append(discovered, goanalysis.FindBlankImports(f)...) fileImports := goanalysis.FormatImports(f) d, err := DiscoverModules(f, chainRoot, fileImports) if err != nil { @@ -114,40 +114,20 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { discovered = append(discovered, m...) } - return mergeImports(blankImports, discovered), nil -} - -// mergeImports merge all discovered imports into the blank imports found in the app files. -func mergeImports(blankImports, discovered []string) []string { - imports := make([]string, len(blankImports)) - copy(imports, blankImports) - for i, m := range discovered { - split := strings.Split(m, "/") - - j := len(split) - maxTrim := len(split) - 3 - LoopBack: - for j > maxTrim { - j-- - // x path means we are reaching the root of the module - if split[j] == "x" { - j = maxTrim - goto LoopBack - } - for _, imp := range blankImports { - // check if the import exist into the blank imports - if strings.Contains(imp, m) { - j = -1 - goto LoopBack - } - } - m = strings.TrimSuffix(m, "/"+split[j]) - } - if j == maxTrim { - imports = append(imports, discovered[i]) + // Remove duplicated entries + var ( + modules []string + seen = make(map[string]struct{}) + ) + for _, m := range discovered { + if _, ok := seen[m]; ok { + continue } + + seen[m] = struct{}{} + modules = append(modules, m) } - return imports + return modules, nil } // DiscoverModules find a map of import modules based on the configured app. From f51da386d97e33527945e97e583636253b66b3fc Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 12:51:57 +0100 Subject: [PATCH 07/17] feat(pkg/xstrings): add `StringBetween` function --- ignite/pkg/xstrings/xstrings.go | 22 ++++++++++++++++++++++ ignite/pkg/xstrings/xstrings_test.go | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/ignite/pkg/xstrings/xstrings.go b/ignite/pkg/xstrings/xstrings.go index ff038a95db..7924443e33 100644 --- a/ignite/pkg/xstrings/xstrings.go +++ b/ignite/pkg/xstrings/xstrings.go @@ -70,3 +70,25 @@ func Title(s string) string { func ToUpperFirst(s string) string { return strings.ToUpper(s[:1]) + s[1:] } + +// StringBetween returns the string between two other strings. +// The comparison is not greedy so the between result includes the +// string between the start value and the first match of the end value. +func StringBetween(s, start, end string) string { + if s == "" || start == "" || end == "" { + return "" + } + + i := strings.Index(s, start) + if i == -1 { + return "" + } + + s = s[i+len(start):] + i = strings.Index(s, end) + if i == -1 { + return "" + } + + return s[:i] +} diff --git a/ignite/pkg/xstrings/xstrings_test.go b/ignite/pkg/xstrings/xstrings_test.go index c2da08be2c..0087b4e6ce 100644 --- a/ignite/pkg/xstrings/xstrings_test.go +++ b/ignite/pkg/xstrings/xstrings_test.go @@ -18,3 +18,11 @@ func TestNoNumberPrefix(t *testing.T) { require.Equal(t, "_0foo", xstrings.NoNumberPrefix("0foo")) require.Equal(t, "_999foo", xstrings.NoNumberPrefix("999foo")) } + +func TestStringBetween(t *testing.T) { + require.Equal(t, "bar", xstrings.StringBetween("foobarbaz", "foo", "baz")) + require.Equal(t, "bar", xstrings.StringBetween("0foobarbaz1", "foo", "baz")) + require.Equal(t, "", xstrings.StringBetween("0foo", "0", "")) + require.Equal(t, "", xstrings.StringBetween("foo0", "", "0")) + require.Equal(t, "", xstrings.StringBetween("", "0", "1")) +} From 108024814cd223cb197eae0e8b6502a9b4903271 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 13:11:30 +0100 Subject: [PATCH 08/17] fix: discover "cosmossdk.io/x" based packages proto files The "cosmossdk.io/x" Go packages MUST search proto files in the Cosmos SDK Go package because these packages don't have the proto files included so they can't be discovered. --- ignite/pkg/cosmosanalysis/app/app.go | 1 + ignite/pkg/cosmosanalysis/app/app_test.go | 118 +----------------- ignite/pkg/cosmosanalysis/module/module.go | 29 ++++- .../pkg/cosmosanalysis/module/module_test.go | 4 +- ignite/pkg/cosmosgen/cosmosgen.go | 1 + ignite/pkg/cosmosgen/generate.go | 77 +++++++----- ignite/pkg/gomodule/gomodule.go | 15 ++- 7 files changed, 88 insertions(+), 157 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index a1a6bb6c99..3773b6bd45 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -341,6 +341,7 @@ func resolveCosmosPackagePath(chainRoot string) (string, error) { } // Check path of the package directory within Go's module cache + // TODO: Change to use "go mod download --json" path := filepath.Join(goenv.GoModCache(), pkg) info, err := os.Stat(path) if os.IsNotExist(err) || !info.IsDir() { diff --git a/ignite/pkg/cosmosanalysis/app/app_test.go b/ignite/pkg/cosmosanalysis/app/app_test.go index 07ee898f61..ba2f9570f7 100644 --- a/ignite/pkg/cosmosanalysis/app/app_test.go +++ b/ignite/pkg/cosmosanalysis/app/app_test.go @@ -113,6 +113,8 @@ func TestFindRegisteredModules(t *testing.T) { "cosmossdk.io/x/evidence", "cosmossdk.io/x/feegrant/module", "cosmossdk.io/x/upgrade", + "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", "github.com/cosmos/cosmos-sdk/x/auth/tx/config", "github.com/cosmos/cosmos-sdk/x/auth/vesting", "github.com/cosmos/cosmos-sdk/x/authz/module", @@ -428,122 +430,6 @@ func TestDiscoverModules(t *testing.T) { } } -func Test_mergeImports(t *testing.T) { - tests := []struct { - name string - blankImports []string - discovered []string - want []string - }{ - { - name: "test nil imports", - blankImports: nil, - discovered: nil, - want: nil, - }, - { - name: "test empty imports", - blankImports: []string{}, - discovered: []string{}, - want: []string{}, - }, - { - name: "test only one blank import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - discovered: []string{}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one discovered import", - blankImports: []string{}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth/keeper"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth"}, - }, - { - name: "test only one keeper import", - blankImports: []string{"github.com/cosmos/cosmos-sdk/x/auth/module"}, - discovered: []string{"github.com/cosmos/cosmos-sdk/x/auth/keeper"}, - want: []string{"github.com/cosmos/cosmos-sdk/x/auth/module"}, - }, - { - name: "test two keeper import", - blankImports: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/module", - "github.com/cosmos/cosmos-sdk/x/bank/module", - }, - discovered: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - want: []string{ - "github.com/cosmos/cosmos-sdk/x/auth/module", - "github.com/cosmos/cosmos-sdk/x/bank/module", - }, - }, - { - name: "test two keeper import", - blankImports: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - want: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - }, - }, - { - name: "test keeper imports", - blankImports: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "cosmossdk.io/x/feegrant/module", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - "cosmossdk.io/x/feegrant/types", - "cosmossdk.io/x/feegrant", - "cosmossdk.io/x/foo", - }, - want: []string{ - "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts", - "github.com/cosmos/cosmos-sdk/x/bank/keeper", - "cosmossdk.io/x/feegrant/module", - "cosmossdk.io/x/foo", - }, - }, - { - name: "test three keeper import", - blankImports: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - discovered: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - want: []string{ - "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts", - "github.com/cosmos/ibc-go/modules/capability", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := mergeImports(tt.blankImports, tt.discovered) - require.ElementsMatch(t, tt.want, got) - }) - } -} - func Test_removeKeeperPkgPath(t *testing.T) { tests := []struct { name string diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index ba6e98f1b1..d1450dc66c 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -14,6 +14,7 @@ import ( "github.com/ignite/cli/ignite/pkg/cosmosanalysis/app" "github.com/ignite/cli/ignite/pkg/gomodule" "github.com/ignite/cli/ignite/pkg/protoanalysis" + "github.com/ignite/cli/ignite/pkg/xstrings" ) // Msgs is a module import path-sdk msgs pair. @@ -83,6 +84,12 @@ type moduleDiscoverer struct { registeredModules []string } +// IsCosmosSDKModulePkg check if a Go import path is a Cosmos SDK package module. +// These type of package have the "cosmossdk.io/x" prefix. +func IsCosmosSDKModulePkg(path string) bool { + return strings.Contains(path, "cosmossdk.io/x/") +} + // Discover discovers and returns modules and their types that are registered in the app // chainRoot is the root path of the chain // sourcePath is the root path of the go module which the proto dir is from @@ -92,7 +99,7 @@ type moduleDiscoverer struct { // 1. Getting all the registered Go modules from the app. // 2. Parsing the proto files to find services and messages. // 3. Check if the proto services are implemented in any of the registered modules. -func Discover(ctx context.Context, chainRoot, sourcePath, protoDir string) ([]Module, error) { +func Discover(ctx context.Context, chainRoot, sourcePath, protoDir, sdkPath string) ([]Module, error) { // find out base Go import path of the blockchain. gm, err := gomodule.ParseAt(sourcePath) if err != nil { @@ -124,8 +131,18 @@ func Discover(ctx context.Context, chainRoot, sourcePath, protoDir string) ([]Mo return []Module{}, nil } + // Switch the proto path for "cosmossdk.io" module packages to the official Cosmos + // SDK package because the module packages doesn't contain the proto files. These + // files are only available from the Cosmos SDK package. + var protoPath string + if sdkPath != "" && IsCosmosSDKModulePkg(sourcePath) { + protoPath = switchCosmosSDKPackagePath(sourcePath, sdkPath) + } else { + protoPath = filepath.Join(sourcePath, protoDir) + } + md := &moduleDiscoverer{ - protoPath: filepath.Join(sourcePath, protoDir), + protoPath: protoPath, sourcePath: sourcePath, basegopath: basegopath, registeredModules: appModules, @@ -420,3 +437,11 @@ func hasPagination(msg protoanalysis.Message) bool { return false } + +func switchCosmosSDKPackagePath(srcPath, sdkPath string) string { + modName := xstrings.StringBetween(srcPath, "/x/", "@") + if modName == "" { + return srcPath + } + return filepath.Join(sdkPath, "proto", "cosmos", modName) +} diff --git a/ignite/pkg/cosmosanalysis/module/module_test.go b/ignite/pkg/cosmosanalysis/module/module_test.go index 0ba79a2f15..6b510a54fa 100644 --- a/ignite/pkg/cosmosanalysis/module/module_test.go +++ b/ignite/pkg/cosmosanalysis/module/module_test.go @@ -156,7 +156,7 @@ func TestDiscover(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, tt.protoDir) + modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, tt.protoDir, "") require.NoError(t, err) require.Equal(t, tt.want, modules) @@ -193,7 +193,7 @@ func TestDiscoverWithAppV2(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, sourcePath, tt.protoDir) + modules, err := module.Discover(ctx, sourcePath, sourcePath, tt.protoDir, "") require.NoError(t, err) require.Equal(t, tt.want, modules) diff --git a/ignite/pkg/cosmosgen/cosmosgen.go b/ignite/pkg/cosmosgen/cosmosgen.go index 507a90c369..bbd11f7c0f 100644 --- a/ignite/pkg/cosmosgen/cosmosgen.go +++ b/ignite/pkg/cosmosgen/cosmosgen.go @@ -123,6 +123,7 @@ type generator struct { gomodPath string opts *generateOptions sdkImport string + sdkPath string deps []gomodule.Version appModules []module.Module appIncludes protoIncludes diff --git a/ignite/pkg/cosmosgen/generate.go b/ignite/pkg/cosmosgen/generate.go index 840b100a8d..4cff6cf739 100644 --- a/ignite/pkg/cosmosgen/generate.go +++ b/ignite/pkg/cosmosgen/generate.go @@ -34,7 +34,8 @@ const ( ) var ( - ErrBufConfig = errors.New("invalid Buf config") + ErrBufConfig = errors.New("invalid Buf config") + ErrMissingSDKDep = errors.New("cosmos SDK dependency not found") protocGlobalInclude = xfilepath.List( xfilepath.JoinFromHome(xfilepath.Path("local/include")), @@ -112,8 +113,9 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } - // Discover any custom modules defined by the user's app - g.appModules, err = g.discoverModules(ctx, g.appPath, g.protoDir) + // Discover any custom modules defined by the user's app. + // Use the configured proto directory to locate app's proto files. + g.appModules, err = module.Discover(ctx, g.appPath, g.appPath, g.protoDir, g.sdkPath) if err != nil { return err } @@ -123,6 +125,19 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } + dep, found := filterCosmosSDKModule(g.deps) + if !found { + return ErrMissingSDKDep + } + + // Find the full path to the Cosmos SDK Go package. + // The path is required to be able to discover proto packages for the + // set of "cosmossdk.io" packages that doesn't contain the proto files. + g.sdkPath, err = gomodule.LocatePath(ctx, g.cacheStorage, g.appPath, dep) + if err != nil { + return err + } + // Go through the Go dependencies of the user's app within go.mod, some of them // might be hosting Cosmos SDK modules that could be in use by user's blockchain. // @@ -153,8 +168,10 @@ func (g *generator) setup(ctx context.Context) (err error) { return err } - // Discover any modules defined by the package - modules, err := g.discoverModules(ctx, path, "") + // Discover any modules defined by the package. + // Use an empty string for proto directory because it will be + // discovered automatically within the dependency package path. + modules, err := module.Discover(ctx, g.appPath, path, "", g.sdkPath) if err != nil { return err } @@ -243,14 +260,21 @@ func (g *generator) resolveIncludes(ctx context.Context, path string) (protoIncl includes := protoIncludes{Paths: paths} - // Check that the app/package proto directory exists - protoPath := filepath.Join(path, g.protoDir) - fi, err := os.Stat(protoPath) - if err != nil && !os.IsNotExist(err) { - return protoIncludes{}, false, err - } else if !fi.IsDir() { - // Just return the global includes when a proto directory doesn't exist - return includes, true, nil + // The "cosmossdk.io" module packages must use SDK's proto path which is + // where all proto files for there type of Go package are. + var protoPath string + if module.IsCosmosSDKModulePkg(path) { + protoPath = filepath.Join(g.sdkPath, "proto") + } else { + // Check that the app/package proto directory exists + protoPath = filepath.Join(path, g.protoDir) + fi, err := os.Stat(protoPath) + if err != nil && !os.IsNotExist(err) { + return protoIncludes{}, false, err + } else if !fi.IsDir() { + // Just return the global includes when a proto directory doesn't exist + return includes, true, nil + } } // Add app's proto path to the list of proto paths @@ -285,24 +309,6 @@ func (g *generator) resolveIncludes(ctx context.Context, path string) (protoIncl return includes, true, nil } -func (g *generator) discoverModules(ctx context.Context, path, protoDir string) ([]module.Module, error) { - var filteredModules []module.Module - modules, err := module.Discover(ctx, g.appPath, path, protoDir) - if err != nil { - return nil, err - } - - protoPath := filepath.Join(path, g.protoDir) - for _, m := range modules { - if !strings.HasPrefix(m.Pkg.Path, protoPath) { - continue - } - filteredModules = append(filteredModules, m) - } - - return filteredModules, nil -} - func (g generator) updateBufModule(ctx context.Context) error { for pkgPath, includes := range g.thirdModuleIncludes { // Skip third party dependencies without proto files @@ -472,3 +478,12 @@ func (g generator) vendorProtoPackage(pkgName, protoPath string) (err error) { return nil } + +func filterCosmosSDKModule(versions []gomodule.Version) (gomodule.Version, bool) { + for _, v := range versions { + if strings.HasPrefix(v.Path, cosmosver.CosmosModulePath) { + return v, true + } + } + return gomodule.Version{}, false +} diff --git a/ignite/pkg/gomodule/gomodule.go b/ignite/pkg/gomodule/gomodule.go index 1418079fcb..c5e08dda12 100644 --- a/ignite/pkg/gomodule/gomodule.go +++ b/ignite/pkg/gomodule/gomodule.go @@ -24,6 +24,9 @@ const pathCacheNamespace = "gomodule.path" // ErrGoModNotFound returned when go.mod file cannot be found for an app. var ErrGoModNotFound = errors.New("go.mod not found") +// Version is an alias to the module version type. +type Version = module.Version + // ParseAt finds and parses go.mod at app's path. func ParseAt(path string) (*modfile.File, error) { gomod, err := os.ReadFile(filepath.Join(path, "go.mod")) @@ -37,8 +40,8 @@ func ParseAt(path string) (*modfile.File, error) { } // FilterVersions filters dependencies under require section by their paths. -func FilterVersions(dependencies []module.Version, paths ...string) []module.Version { - var filtered []module.Version +func FilterVersions(dependencies []Version, paths ...string) []Version { + var filtered []Version for _, dep := range dependencies { for _, path := range paths { @@ -52,10 +55,10 @@ func FilterVersions(dependencies []module.Version, paths ...string) []module.Ver return filtered } -func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]module.Version, error) { - var versions []module.Version +func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]Version, error) { + var versions []Version - isReplacementAdded := func(rv module.Version) bool { + isReplacementAdded := func(rv Version) bool { for _, rep := range f.Replace { if rv.Path == rep.Old.Path { versions = append(versions, rep.New) @@ -80,7 +83,7 @@ func ResolveDependencies(f *modfile.File, includeIndirect bool) ([]module.Versio } // LocatePath locates pkg's absolute path managed by 'go mod' on the local filesystem. -func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg module.Version) (path string, err error) { +func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg Version) (path string, err error) { // can be a local package. if pkg.Version == "" { // indicates that this is a local package. if filepath.IsAbs(pkg.Path) { From a8cbc6237ec001999ca812b95ab8d8d80f92f051 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 15:50:30 +0100 Subject: [PATCH 09/17] feat(pkg/gocmd): add Go mod download support --- ignite/pkg/gocmd/gocmd.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ignite/pkg/gocmd/gocmd.go b/ignite/pkg/gocmd/gocmd.go index f9a99c7330..0d043568cf 100644 --- a/ignite/pkg/gocmd/gocmd.go +++ b/ignite/pkg/gocmd/gocmd.go @@ -33,6 +33,9 @@ const ( // CommandModVerify represents go mod "verify" command. CommandModVerify = "verify" + // CommandModDownload represents go mod "download" command. + CommandModDownload = "download" + // CommandFmt represents go "fmt" command. CommandFmt = "fmt" @@ -105,6 +108,15 @@ func ModVerify(ctx context.Context, path string, options ...exec.Option) error { return exec.Exec(ctx, []string{Name(), CommandMod, CommandModVerify}, append(options, exec.StepOption(step.Workdir(path)))...) } +// ModDownload runs go mod download on a path with options. +func ModDownload(ctx context.Context, path string, json bool, options ...exec.Option) error { + command := []string{Name(), CommandMod, CommandModDownload} + if json { + command = append(command, "-json") + } + return exec.Exec(ctx, command, append(options, exec.StepOption(step.Workdir(path)))...) +} + // BuildPath runs go install on cmd folder with options. func BuildPath(ctx context.Context, output, binary, path string, flags []string, options ...exec.Option) error { binaryOutput, err := binaryPath(output, binary) From 2f64b044ee77bcb2b29e33996d02103637aa46fd Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 15:51:22 +0100 Subject: [PATCH 10/17] feat(pkg/cosmosanalysis): add find module support --- ignite/pkg/gomodule/gomodule.go | 90 ++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/ignite/pkg/gomodule/gomodule.go b/ignite/pkg/gomodule/gomodule.go index c5e08dda12..0ce75f25d4 100644 --- a/ignite/pkg/gomodule/gomodule.go +++ b/ignite/pkg/gomodule/gomodule.go @@ -10,23 +10,42 @@ import ( "io/fs" "os" "path/filepath" + "strings" "golang.org/x/mod/modfile" "golang.org/x/mod/module" "github.com/ignite/cli/ignite/pkg/cache" - "github.com/ignite/cli/ignite/pkg/cmdrunner" + "github.com/ignite/cli/ignite/pkg/cmdrunner/exec" "github.com/ignite/cli/ignite/pkg/cmdrunner/step" + "github.com/ignite/cli/ignite/pkg/gocmd" ) const pathCacheNamespace = "gomodule.path" -// ErrGoModNotFound returned when go.mod file cannot be found for an app. -var ErrGoModNotFound = errors.New("go.mod not found") +var ( + // ErrGoModNotFound returned when go.mod file cannot be found for an app. + ErrGoModNotFound = errors.New("go.mod not found") + + // ErrModuleNotFound is returned when a Go module is not found. + ErrModuleNotFound = errors.New("module not found") +) // Version is an alias to the module version type. type Version = module.Version +// Module contains Go module info. +type Module struct { + // Path is the Go module path. + Path string + + // Version is the module version. + Version string + + // Dir is the absolute path to the Go module. + Dir string +} + // ParseAt finds and parses go.mod at app's path. func ParseAt(path string) (*modfile.File, error) { gomod, err := os.ReadFile(filepath.Join(path, "go.mod")) @@ -103,37 +122,60 @@ func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg } // otherwise, it is hosted. - out := &bytes.Buffer{} - - if err := cmdrunner. - New(). - Run(ctx, step.New( - step.Exec("go", "mod", "download", "-json"), - step.Workdir(src), - step.Stdout(out), - )); err != nil { + m, err := FindModule(ctx, src, pkg.String()) + if err != nil { return "", err } - d := json.NewDecoder(out) + if err = pathCache.Put(cacheKey, m.Dir); err != nil { + return "", err + } + return m.Dir, nil +} + +// SplitPath splits a Go import path into an URI path and version. +// Version is an empty string when the path doesn't contain a version suffix. +// Versioned paths use the "path@version" format. +func SplitPath(path string) (string, string) { + parts := strings.SplitN(path, "@", 2) + if len(parts) == 2 { + return parts[0], parts[1] + } + return parts[0], "" +} + +// JoinPath joins a Go import path URI to a version. +// The result path have the "path@version" format. +func JoinPath(path, version string) string { + return fmt.Sprintf("%s@%s", path, version) +} + +// FindModule returns the Go module info for an import path. +// The module is searched within the dependencies of the module defined in root dir. +func FindModule(ctx context.Context, rootDir, path string) (Module, error) { + var stdout bytes.Buffer + err := gocmd.ModDownload(ctx, rootDir, true, exec.StepOption(step.Stdout(&stdout))) + if err != nil { + return Module{}, err + } + + dec := json.NewDecoder(&stdout) + p, version := SplitPath(path) for { - var mod struct { - Path, Version, Dir string - } - if err := d.Decode(&mod); err != nil { + var m Module + if dec.Decode(&m); err != nil { if errors.Is(err, io.EOF) { break } - return "", err + + return Module{}, err } - if mod.Path == pkg.Path && mod.Version == pkg.Version { - if err := pathCache.Put(cacheKey, mod.Dir); err != nil { - return "", err - } - return mod.Dir, nil + + if m.Path == p && (version == "" || version == m.Version) { + return m, nil } } - return "", fmt.Errorf("module %q not found", pkg.Path) + return Module{}, fmt.Errorf("%w: %s", ErrModuleNotFound, path) } From a7083811de7e3405d8a7abeca9c4d9419122a004 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 15:55:25 +0100 Subject: [PATCH 11/17] refactor(pkg/cosmosanalysis): change Cosmos SDK package path discovery Discovery changed to use go mod download instead of using Go's module path which might not be present in some context. --- ignite/pkg/cosmosanalysis/app/app.go | 13 +- ignite/pkg/cosmosanalysis/app/app_test.go | 6 + .../app/testdata/modules/spn/go.mod | 347 +++++++++++++++++- 3 files changed, 340 insertions(+), 26 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 3773b6bd45..6777365579 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -1,6 +1,7 @@ package app import ( + "context" "errors" "fmt" "go/ast" @@ -13,7 +14,6 @@ import ( "github.com/ignite/cli/ignite/pkg/cosmosanalysis" "github.com/ignite/cli/ignite/pkg/cosmosver" "github.com/ignite/cli/ignite/pkg/goanalysis" - "github.com/ignite/cli/ignite/pkg/goenv" "github.com/ignite/cli/ignite/pkg/gomodule" "github.com/ignite/cli/ignite/pkg/xast" ) @@ -340,14 +340,11 @@ func resolveCosmosPackagePath(chainRoot string) (string, error) { return "", errors.New("cosmos SDK package version not found") } - // Check path of the package directory within Go's module cache - // TODO: Change to use "go mod download --json" - path := filepath.Join(goenv.GoModCache(), pkg) - info, err := os.Stat(path) - if os.IsNotExist(err) || !info.IsDir() { - return "", errors.New("local path to Cosmos SDK package not found") + m, err := gomodule.FindModule(context.Background(), chainRoot, pkg) + if err != nil { + return "", err } - return path, nil + return m.Dir, nil } func findRegisterAPIRoutesRegistrations(n ast.Node) []string { diff --git a/ignite/pkg/cosmosanalysis/app/app_test.go b/ignite/pkg/cosmosanalysis/app/app_test.go index ba2f9570f7..be4cf1aeb7 100644 --- a/ignite/pkg/cosmosanalysis/app/app_test.go +++ b/ignite/pkg/cosmosanalysis/app/app_test.go @@ -198,6 +198,9 @@ func TestFindRegisteredModules(t *testing.T) { path: "testdata/modules/spn", expectedModules: []string{ "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/capability", "github.com/cosmos/cosmos-sdk/x/staking", @@ -356,6 +359,9 @@ func TestDiscoverModules(t *testing.T) { path: "testdata/modules/spn", expectedModules: []string{ "github.com/cosmos/cosmos-sdk/x/auth", + "github.com/cosmos/cosmos-sdk/x/auth/tx", + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice", + "github.com/cosmos/cosmos-sdk/client/grpc/node", "github.com/cosmos/cosmos-sdk/x/bank", "github.com/cosmos/cosmos-sdk/x/capability", "github.com/cosmos/cosmos-sdk/x/staking", diff --git a/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod index 46b9f1988b..39414c01ea 100644 --- a/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod +++ b/ignite/pkg/cosmosanalysis/app/testdata/modules/spn/go.mod @@ -3,30 +3,341 @@ module github.com/tendermint/spn go 1.19 require ( + cosmossdk.io/api v0.3.1 cosmossdk.io/errors v1.0.0-beta.7 - cosmossdk.io/math v1.0.0-beta.4 + cosmossdk.io/math v1.0.1 github.com/aws/smithy-go v1.8.0 - github.com/cosmos/cosmos-proto v1.0.0-beta.1 - github.com/cosmos/cosmos-sdk v0.46.7 - github.com/cosmos/ibc-go/v6 v6.0.0 - github.com/gogo/protobuf v1.3.3 - github.com/golang/protobuf v1.5.2 + github.com/bufbuild/buf v1.22.0 + github.com/cometbft/cometbft v0.37.2 + github.com/cometbft/cometbft-db v0.8.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.2 + github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/gogo/protobuf v1.3.2 + github.com/golang/protobuf v1.5.3 github.com/golangci/golangci-lint v1.50.1 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/ignite/modules v0.0.0-20221215224430-496fd9a7820c + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 + github.com/ignite/modules v0.0.2 github.com/pkg/errors v0.9.1 - github.com/spf13/cast v1.5.0 - github.com/spf13/cobra v1.6.1 + github.com/spf13/cast v1.5.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.1 - github.com/tendermint/fundraising v0.3.1 - github.com/tendermint/tendermint v0.34.24 - github.com/tendermint/tm-db v0.6.7 - golang.org/x/tools v0.2.0 - google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1 - google.golang.org/grpc v1.50.1 - google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 + github.com/stretchr/testify v1.8.4 + github.com/tendermint/fundraising v0.4.1 + golang.org/x/tools v0.10.0 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 - mvdan.cc/gofumpt v0.4.0 + mvdan.cc/gofumpt v0.5.0 +) + +replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + +require ( + 4d63.com/gochecknoglobals v0.1.0 // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.0.0 // indirect + cloud.google.com/go/storage v1.30.1 // indirect + cosmossdk.io/core v0.5.1 // indirect + cosmossdk.io/depinject v1.0.0-alpha.3 // indirect + cosmossdk.io/log v1.1.0 // indirect + cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff // indirect + cosmossdk.io/tools/rosetta v0.2.1 // indirect + filippo.io/edwards25519 v1.0.0 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.1 // indirect + github.com/Abirdcfly/dupword v0.0.7 // indirect + github.com/Antonboom/errname v0.1.7 // indirect + github.com/Antonboom/nilnil v0.1.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect + github.com/Masterminds/semver v1.5.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/OpenPeeDeeP/depguard v1.1.1 // indirect + github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alingse/asasalint v0.0.11 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/ashanbrown/forbidigo v1.3.0 // indirect + github.com/ashanbrown/makezero v1.1.1 // indirect + github.com/aws/aws-sdk-go v1.44.244 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect + github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bkielbasa/cyclop v1.2.0 // indirect + github.com/blizzy78/varnamelen v0.8.0 // indirect + github.com/bombsimon/wsl/v3 v3.3.0 // indirect + github.com/breml/bidichk v0.2.3 // indirect + github.com/breml/errchkjson v0.3.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/bufbuild/connect-go v1.8.0 // indirect + github.com/bufbuild/connect-opentelemetry-go v0.3.0 // indirect + github.com/bufbuild/protocompile v0.5.1 // indirect + github.com/butuzov/ireturn v0.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charithe/durationcheck v0.0.9 // indirect + github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cockroachdb/apd/v2 v2.0.2 // indirect + github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect + github.com/confio/ics23/go v0.9.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogogateway v1.2.0 // indirect + github.com/cosmos/iavl v0.20.0 // indirect + github.com/cosmos/ics23/go v0.10.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/curioswitch/go-reassign v0.2.0 // indirect + github.com/daixiang0/gci v0.8.1 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/denis-tingaikin/go-header v0.4.3 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/cli v24.0.2+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/esimonov/ifshort v1.0.4 // indirect + github.com/ettle/strcase v0.1.1 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/fatih/structtag v1.2.0 // indirect + github.com/felixge/fgprof v0.9.3 // indirect + github.com/felixge/httpsnoop v1.0.2 // indirect + github.com/firefart/nonamedreturns v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fzipp/gocyclo v0.6.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect + github.com/go-critic/go-critic v0.6.5 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-toolsmith/astcast v1.0.0 // indirect + github.com/go-toolsmith/astcopy v1.0.2 // indirect + github.com/go-toolsmith/astequal v1.0.3 // indirect + github.com/go-toolsmith/astfmt v1.0.0 // indirect + github.com/go-toolsmith/astp v1.0.0 // indirect + github.com/go-toolsmith/strparse v1.0.0 // indirect + github.com/go-toolsmith/typep v1.0.2 // indirect + github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/uuid/v5 v5.0.0 // indirect + github.com/gogo/googleapis v1.4.1 // indirect + github.com/golang/glog v1.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect + github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect + github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect + github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect + github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect + github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect + github.com/golangci/misspell v0.3.5 // indirect + github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect + github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-containerregistry v0.15.2 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect + github.com/google/s2a-go v0.1.3 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.8.0 // indirect + github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gostaticanalysis/analysisutil v0.7.1 // indirect + github.com/gostaticanalysis/comment v1.4.2 // indirect + github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect + github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-safetemp v1.0.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.1.0 // indirect + github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/huandu/skiplist v1.2.0 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect + github.com/jgautheron/goconst v1.5.1 // indirect + github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/julz/importas v0.1.0 // indirect + github.com/kisielk/errcheck v1.6.2 // indirect + github.com/kisielk/gotool v1.0.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.3 // indirect + github.com/klauspost/compress v1.16.6 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/kulti/thelper v0.6.3 // indirect + github.com/kunwardeep/paralleltest v1.0.6 // indirect + github.com/kyoh86/exportloopref v0.1.8 // indirect + github.com/ldez/gomoddirectives v0.2.3 // indirect + github.com/ldez/tagliatelle v0.3.1 // indirect + github.com/leonklingele/grouper v1.1.0 // indirect + github.com/lib/pq v1.10.7 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/lufeee/execinquery v1.2.1 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect + github.com/maratori/testableexamples v1.0.0 // indirect + github.com/maratori/testpackage v1.1.0 // indirect + github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mbilski/exhaustivestruct v1.2.0 // indirect + github.com/mgechev/revive v1.2.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/minio/highwayhash v1.0.2 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/moricho/tparallel v0.2.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/nakabonne/nestif v0.3.1 // indirect + github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect + github.com/nishanths/exhaustive v0.8.3 // indirect + github.com/nishanths/predeclared v0.2.2 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/profile v1.7.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/polyfloyd/go-errorlint v1.0.5 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/quasilyte/go-ruleguard v0.3.18 // indirect + github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect + github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect + github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect + github.com/rakyll/statik v0.1.7 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rs/cors v1.9.0 // indirect + github.com/rs/zerolog v1.29.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/ryancurrah/gomodguard v1.2.4 // indirect + github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect + github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sashamelentyev/interfacebloat v1.1.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.20.0 // indirect + github.com/securego/gosec/v2 v2.13.1 // indirect + github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sivchari/containedctx v1.0.2 // indirect + github.com/sivchari/nosnakecase v1.7.0 // indirect + github.com/sivchari/tenv v1.7.0 // indirect + github.com/sonatard/noctx v0.0.1 // indirect + github.com/sourcegraph/go-diff v0.6.1 // indirect + github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/viper v1.16.0 // indirect + github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect + github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tdakkota/asciicheck v0.1.1 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tetafro/godot v1.4.11 // indirect + github.com/tetratelabs/wazero v1.2.1 // indirect + github.com/tidwall/btree v1.6.0 // indirect + github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect + github.com/timonwong/loggercheck v0.9.3 // indirect + github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/ultraware/funlen v0.0.3 // indirect + github.com/ultraware/whitespace v0.0.5 // indirect + github.com/uudashr/gocognit v1.0.6 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect + github.com/yagipy/maintidx v1.0.0 // indirect + github.com/yeya24/promlinter v0.2.0 // indirect + github.com/zondax/hid v0.9.1 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect + gitlab.com/bosi/decorder v0.2.3 // indirect + go.etcd.io/bbolt v1.3.7 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/otel/sdk v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.10.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect + golang.org/x/mod v0.11.0 // indirect + golang.org/x/net v0.11.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/term v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + google.golang.org/api v0.122.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + honnef.co/go/tools v0.3.3 // indirect + mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect + mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect + mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 // indirect + nhooyr.io/websocket v1.8.6 // indirect + pgregory.net/rapid v0.5.5 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) From ffaa1ec8264575f426f3e9f694caa482f39c1f1f Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Fri, 1 Dec 2023 23:35:11 +0100 Subject: [PATCH 12/17] refactor: add filter function to remove duplicated modules --- ignite/pkg/cosmosanalysis/app/app.go | 34 ++++++++-------------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/ignite/pkg/cosmosanalysis/app/app.go b/ignite/pkg/cosmosanalysis/app/app.go index 6777365579..85e54ab098 100644 --- a/ignite/pkg/cosmosanalysis/app/app.go +++ b/ignite/pkg/cosmosanalysis/app/app.go @@ -114,20 +114,7 @@ func FindRegisteredModules(chainRoot string) ([]string, error) { discovered = append(discovered, m...) } - // Remove duplicated entries - var ( - modules []string - seen = make(map[string]struct{}) - ) - for _, m := range discovered { - if _, ok := seen[m]; ok { - continue - } - - seen[m] = struct{}{} - modules = append(modules, m) - } - return modules, nil + return removeDuplicateEntries(discovered), nil } // DiscoverModules find a map of import modules based on the configured app. @@ -159,21 +146,20 @@ func DiscoverModules(file *ast.File, chainRoot string, fileImports map[string]st } } } + return removeDuplicateEntries(discovered), nil +} - // Add discovered modules to a list without duplicates - var ( - modules []string - skip = make(map[string]struct{}) - ) - for _, name := range discovered { - if _, ok := skip[name]; ok { +func removeDuplicateEntries(entries []string) (res []string) { + seen := make(map[string]struct{}) + for _, e := range entries { + if _, ok := seen[e]; ok { continue } - skip[name] = struct{}{} - modules = append(modules, name) + seen[e] = struct{}{} + res = append(res, e) } - return modules, nil + return } func discoverKeeperModules(d *ast.GenDecl, appTypeName string, imports map[string]string) []string { From af8086c78092f95060faf712db7ffccefd17ba09 Mon Sep 17 00:00:00 2001 From: Clockwork Date: Sat, 2 Dec 2023 09:05:49 +0200 Subject: [PATCH 13/17] chore: TS template updates --- ignite/pkg/cosmosgen/templates/module/index.ts.tpl | 4 ++-- ignite/pkg/cosmosgen/templates/module/module.ts.tpl | 4 ++-- ignite/pkg/cosmosgen/templates/root/client.ts.tpl | 6 +++--- ignite/pkg/cosmosgen/templates/root/index.ts.tpl | 2 +- ignite/pkg/cosmosgen/templates/root/modules.ts.tpl | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ignite/pkg/cosmosgen/templates/module/index.ts.tpl b/ignite/pkg/cosmosgen/templates/module/index.ts.tpl index c9dfa159ec..11faba741d 100644 --- a/ignite/pkg/cosmosgen/templates/module/index.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/module/index.ts.tpl @@ -1,6 +1,6 @@ -import Module from './module'; +import IgntModule from './module'; import { txClient, queryClient, registry } from './module'; import { msgTypes } from './registry'; export * from "./types"; -export { Module, msgTypes, txClient, queryClient, registry }; +export { IgntModule, msgTypes, txClient, queryClient, registry }; diff --git a/ignite/pkg/cosmosgen/templates/module/module.ts.tpl b/ignite/pkg/cosmosgen/templates/module/module.ts.tpl index 4797df2b06..abb378e19b 100644 --- a/ignite/pkg/cosmosgen/templates/module/module.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/module/module.ts.tpl @@ -119,7 +119,7 @@ class SDKModule { } }; -const Module = (test: IgniteClient) => { +const IgntModule = (test: IgniteClient) => { return { module: { {{ camelCaseUpperSta .Module.Pkg.Name }}: new SDKModule(test) @@ -127,4 +127,4 @@ const Module = (test: IgniteClient) => { registry: msgTypes } } -export default Module; \ No newline at end of file +export default IgntModule; \ No newline at end of file diff --git a/ignite/pkg/cosmosgen/templates/root/client.ts.tpl b/ignite/pkg/cosmosgen/templates/root/client.ts.tpl index a7b30495b6..a9088ce67b 100644 --- a/ignite/pkg/cosmosgen/templates/root/client.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/client.ts.tpl @@ -8,7 +8,7 @@ import { import { SigningStargateClient, StdFee } from "@cosmjs/stargate"; import { Env } from "./env"; import { UnionToIntersection, Return, Constructor } from "./helpers"; -import { Module } from "./modules"; +import { IgntModule } from "./modules"; import { EventEmitter } from "events"; import { ChainInfo } from "@keplr-wallet/types"; @@ -18,11 +18,11 @@ const defaultFee = { }; export class IgniteClient extends EventEmitter { - static plugins: Module[] = []; + static plugins: IgntModule[] = []; env: Env; signer?: OfflineSigner; registry: Array<[string, GeneratedType]> = []; - static plugin(plugin: T) { + static plugin(plugin: T) { const currentPlugins = this.plugins; class AugmentedClient extends this { diff --git a/ignite/pkg/cosmosgen/templates/root/index.ts.tpl b/ignite/pkg/cosmosgen/templates/root/index.ts.tpl index 8c71febfe1..b2cd682a81 100644 --- a/ignite/pkg/cosmosgen/templates/root/index.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/index.ts.tpl @@ -2,7 +2,7 @@ import { Registry } from '@cosmjs/proto-signing' import { IgniteClient } from "./client"; import { MissingWalletError } from "./helpers"; -{{ range .Modules }}import { Module as {{ camelCaseUpperSta .Pkg.Name }}, msgTypes as {{ camelCaseUpperSta .Pkg.Name }}MsgTypes } from './{{ .Pkg.Name }}' +{{ range .Modules }}import { IgntModule as {{ camelCaseUpperSta .Pkg.Name }}, msgTypes as {{ camelCaseUpperSta .Pkg.Name }}MsgTypes } from './{{ .Pkg.Name }}' {{ end }} const Client = IgniteClient.plugin([ diff --git a/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl b/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl index 634b83c125..e8e4a78272 100644 --- a/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl +++ b/ignite/pkg/cosmosgen/templates/root/modules.ts.tpl @@ -1,5 +1,5 @@ import { IgniteClient } from "./client"; import { GeneratedType } from "@cosmjs/proto-signing"; -export type ModuleInterface = { [key: string]: any } -export type Module = (instance: IgniteClient) => { module: ModuleInterface, registry: [string, GeneratedType][] } +export type IgntModuleInterface = { [key: string]: any } +export type IgntModule = (instance: IgniteClient) => { module: IgntModuleInterface, registry: [string, GeneratedType][] } From b9b090a3324b811c9c01bc40292468ae59cf32b6 Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Sat, 2 Dec 2023 13:04:24 +0100 Subject: [PATCH 14/17] fix: correct TS imports for generated "cosmossdk.io" module packages --- ignite/pkg/cosmosgen/generate_typescript.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ignite/pkg/cosmosgen/generate_typescript.go b/ignite/pkg/cosmosgen/generate_typescript.go index 328eb69b51..cfc8726ea7 100644 --- a/ignite/pkg/cosmosgen/generate_typescript.go +++ b/ignite/pkg/cosmosgen/generate_typescript.go @@ -196,7 +196,14 @@ func (g *tsGenerator) generateModuleTemplate( return err } - pp := filepath.Join(appPath, g.g.protoDir) + // All "cosmossdk.io" module packages must use SDK's + // proto path which is where the proto files are stored. + var pp string + if module.IsCosmosSDKModulePkg(appPath) { + pp = filepath.Join(g.g.sdkPath, "proto") + } else { + pp = filepath.Join(appPath, g.g.protoDir) + } return templateTSClientModule.Write(out, pp, struct { Module module.Module From 14137e30901e993208a9df38a85bba3edbb2298e Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Sun, 3 Dec 2023 12:25:47 +0100 Subject: [PATCH 15/17] tests: add unit tests for the new `pkg/gomodule` functions --- ignite/pkg/gomodule/gomodule.go | 14 +++- ignite/pkg/gomodule/gomodule_test.go | 97 ++++++++++++++++++++++ ignite/pkg/gomodule/testdata/module/go.mod | 8 ++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 ignite/pkg/gomodule/gomodule_test.go create mode 100644 ignite/pkg/gomodule/testdata/module/go.mod diff --git a/ignite/pkg/gomodule/gomodule.go b/ignite/pkg/gomodule/gomodule.go index 0ce75f25d4..2c4d0af13a 100644 --- a/ignite/pkg/gomodule/gomodule.go +++ b/ignite/pkg/gomodule/gomodule.go @@ -137,6 +137,10 @@ func LocatePath(ctx context.Context, cacheStorage cache.Storage, src string, pkg // Version is an empty string when the path doesn't contain a version suffix. // Versioned paths use the "path@version" format. func SplitPath(path string) (string, string) { + if len(path) == 0 || path[0] == '@' { + return "", "" + } + parts := strings.SplitN(path, "@", 2) if len(parts) == 2 { return parts[0], parts[1] @@ -147,6 +151,14 @@ func SplitPath(path string) (string, string) { // JoinPath joins a Go import path URI to a version. // The result path have the "path@version" format. func JoinPath(path, version string) string { + if path == "" { + return "" + } + + if version == "" { + return path + } + return fmt.Sprintf("%s@%s", path, version) } @@ -162,7 +174,7 @@ func FindModule(ctx context.Context, rootDir, path string) (Module, error) { dec := json.NewDecoder(&stdout) p, version := SplitPath(path) - for { + for dec.More() { var m Module if dec.Decode(&m); err != nil { if errors.Is(err, io.EOF) { diff --git a/ignite/pkg/gomodule/gomodule_test.go b/ignite/pkg/gomodule/gomodule_test.go new file mode 100644 index 0000000000..42ff3e6d2a --- /dev/null +++ b/ignite/pkg/gomodule/gomodule_test.go @@ -0,0 +1,97 @@ +package gomodule_test + +import ( + "context" + "strings" + "testing" + + "github.com/ignite/cli/ignite/pkg/gomodule" + "github.com/stretchr/testify/require" +) + +func TestSplitPath(t *testing.T) { + cases := []struct { + name string + path string + wantPath string + wantVersion string + }{ + { + name: "path with version", + path: "foo@v0.1.0", + wantPath: "foo", + wantVersion: "v0.1.0", + }, + { + name: "path without version", + path: "foo", + wantPath: "foo", + }, + { + name: "invalid path", + path: "@v0.1.0", + }, + { + name: "empty path", + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + // Act + p, v := gomodule.SplitPath(tt.path) + + // Assert + require.Equal(t, tt.wantPath, p) + require.Equal(t, tt.wantVersion, v) + }) + } +} + +func TestJoinPath(t *testing.T) { + require.Equal(t, "foo@v0.1.0", gomodule.JoinPath("foo", "v0.1.0")) + require.Equal(t, "", gomodule.JoinPath("", "v0.1.0")) + require.Equal(t, "foo", gomodule.JoinPath("foo", "")) +} + +func TestFindModule(t *testing.T) { + cases := []struct { + name string + importPath string + version string + wantErr error + }{ + { + name: "module exists", + importPath: "github.com/gorilla/mux", + version: "v1.8.0", + }, + { + name: "module missing", + importPath: "github.com/foo/bar", + version: "v0.1.0", + wantErr: gomodule.ErrModuleNotFound, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + // Arrange + ctx := context.Background() + path := gomodule.JoinPath(tt.importPath, tt.version) + + // Act + m, err := gomodule.FindModule(ctx, "testdata/module", path) + + // Assert + if tt.wantErr != nil { + require.ErrorIs(t, err, tt.wantErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.importPath, m.Path) + require.Equal(t, tt.version, m.Version) + require.True(t, strings.HasSuffix(m.Dir, path)) + } + }) + } +} diff --git a/ignite/pkg/gomodule/testdata/module/go.mod b/ignite/pkg/gomodule/testdata/module/go.mod new file mode 100644 index 0000000000..6b0c1f1e4c --- /dev/null +++ b/ignite/pkg/gomodule/testdata/module/go.mod @@ -0,0 +1,8 @@ +module github.com/ignite/cli/ignite/pkg/gomodule + +go 1.21.0 + +require ( + github.com/gorilla/mux v1.8.0 + github.com/stretchr/testify v1.8.2 +) From 0181c5f5c06237e0260d447ca2294a67d90497ed Mon Sep 17 00:00:00 2001 From: jeronimoalbi Date: Sun, 3 Dec 2023 12:57:34 +0100 Subject: [PATCH 16/17] refactor: add options to `pkg/cosmosanalysis` Discover function --- ignite/pkg/cosmosanalysis/module/module.go | 17 +++++++++----- .../pkg/cosmosanalysis/module/module_test.go | 4 ++-- ignite/pkg/cosmosanalysis/module/options.go | 22 +++++++++++++++++++ ignite/pkg/cosmosgen/cosmosgen.go | 2 +- ignite/pkg/cosmosgen/generate.go | 14 ++++++++---- ignite/pkg/cosmosgen/generate_typescript.go | 2 +- 6 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 ignite/pkg/cosmosanalysis/module/options.go diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index d1450dc66c..cdfe90e9d6 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -99,7 +99,12 @@ func IsCosmosSDKModulePkg(path string) bool { // 1. Getting all the registered Go modules from the app. // 2. Parsing the proto files to find services and messages. // 3. Check if the proto services are implemented in any of the registered modules. -func Discover(ctx context.Context, chainRoot, sourcePath, protoDir, sdkPath string) ([]Module, error) { +func Discover(ctx context.Context, chainRoot, sourcePath string, options ...DiscoverOption) ([]Module, error) { + var o discoverOptions + for _, apply := range options { + apply(&o) + } + // find out base Go import path of the blockchain. gm, err := gomodule.ParseAt(sourcePath) if err != nil { @@ -135,10 +140,10 @@ func Discover(ctx context.Context, chainRoot, sourcePath, protoDir, sdkPath stri // SDK package because the module packages doesn't contain the proto files. These // files are only available from the Cosmos SDK package. var protoPath string - if sdkPath != "" && IsCosmosSDKModulePkg(sourcePath) { - protoPath = switchCosmosSDKPackagePath(sourcePath, sdkPath) + if o.sdkDir != "" && IsCosmosSDKModulePkg(sourcePath) { + protoPath = switchCosmosSDKPackagePath(sourcePath, o.sdkDir) } else { - protoPath = filepath.Join(sourcePath, protoDir) + protoPath = filepath.Join(sourcePath, o.protoDir) } md := &moduleDiscoverer{ @@ -438,10 +443,10 @@ func hasPagination(msg protoanalysis.Message) bool { return false } -func switchCosmosSDKPackagePath(srcPath, sdkPath string) string { +func switchCosmosSDKPackagePath(srcPath, sdkDir string) string { modName := xstrings.StringBetween(srcPath, "/x/", "@") if modName == "" { return srcPath } - return filepath.Join(sdkPath, "proto", "cosmos", modName) + return filepath.Join(sdkDir, "proto", "cosmos", modName) } diff --git a/ignite/pkg/cosmosanalysis/module/module_test.go b/ignite/pkg/cosmosanalysis/module/module_test.go index 6b510a54fa..2db58c75fd 100644 --- a/ignite/pkg/cosmosanalysis/module/module_test.go +++ b/ignite/pkg/cosmosanalysis/module/module_test.go @@ -156,7 +156,7 @@ func TestDiscover(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, tt.protoDir, "") + modules, err := module.Discover(ctx, sourcePath, tt.sourcePath, module.WithProtoDir(tt.protoDir)) require.NoError(t, err) require.Equal(t, tt.want, modules) @@ -193,7 +193,7 @@ func TestDiscoverWithAppV2(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - modules, err := module.Discover(ctx, sourcePath, sourcePath, tt.protoDir, "") + modules, err := module.Discover(ctx, sourcePath, sourcePath, module.WithProtoDir(tt.protoDir)) require.NoError(t, err) require.Equal(t, tt.want, modules) diff --git a/ignite/pkg/cosmosanalysis/module/options.go b/ignite/pkg/cosmosanalysis/module/options.go new file mode 100644 index 0000000000..20820785f8 --- /dev/null +++ b/ignite/pkg/cosmosanalysis/module/options.go @@ -0,0 +1,22 @@ +package module + +// DiscoverOption configures calls to Discovery function. +type DiscoverOption func(*discoverOptions) + +type discoverOptions struct { + protoDir, sdkDir string +} + +// WithProtoDir sets the relative proto directory path. +func WithProtoDir(path string) DiscoverOption { + return func(o *discoverOptions) { + o.protoDir = path + } +} + +// WithSDKDir sets the absolute directory path to the Cosmos SDK Go package. +func WithSDKDir(path string) DiscoverOption { + return func(o *discoverOptions) { + o.sdkDir = path + } +} diff --git a/ignite/pkg/cosmosgen/cosmosgen.go b/ignite/pkg/cosmosgen/cosmosgen.go index bbd11f7c0f..89a188eea5 100644 --- a/ignite/pkg/cosmosgen/cosmosgen.go +++ b/ignite/pkg/cosmosgen/cosmosgen.go @@ -123,7 +123,7 @@ type generator struct { gomodPath string opts *generateOptions sdkImport string - sdkPath string + sdkDir string deps []gomodule.Version appModules []module.Module appIncludes protoIncludes diff --git a/ignite/pkg/cosmosgen/generate.go b/ignite/pkg/cosmosgen/generate.go index 4cff6cf739..a6402671a9 100644 --- a/ignite/pkg/cosmosgen/generate.go +++ b/ignite/pkg/cosmosgen/generate.go @@ -115,7 +115,13 @@ func (g *generator) setup(ctx context.Context) (err error) { // Discover any custom modules defined by the user's app. // Use the configured proto directory to locate app's proto files. - g.appModules, err = module.Discover(ctx, g.appPath, g.appPath, g.protoDir, g.sdkPath) + g.appModules, err = module.Discover( + ctx, + g.appPath, + g.appPath, + module.WithProtoDir(g.protoDir), + module.WithSDKDir(g.sdkDir), + ) if err != nil { return err } @@ -133,7 +139,7 @@ func (g *generator) setup(ctx context.Context) (err error) { // Find the full path to the Cosmos SDK Go package. // The path is required to be able to discover proto packages for the // set of "cosmossdk.io" packages that doesn't contain the proto files. - g.sdkPath, err = gomodule.LocatePath(ctx, g.cacheStorage, g.appPath, dep) + g.sdkDir, err = gomodule.LocatePath(ctx, g.cacheStorage, g.appPath, dep) if err != nil { return err } @@ -171,7 +177,7 @@ func (g *generator) setup(ctx context.Context) (err error) { // Discover any modules defined by the package. // Use an empty string for proto directory because it will be // discovered automatically within the dependency package path. - modules, err := module.Discover(ctx, g.appPath, path, "", g.sdkPath) + modules, err := module.Discover(ctx, g.appPath, path, module.WithSDKDir(g.sdkDir)) if err != nil { return err } @@ -264,7 +270,7 @@ func (g *generator) resolveIncludes(ctx context.Context, path string) (protoIncl // where all proto files for there type of Go package are. var protoPath string if module.IsCosmosSDKModulePkg(path) { - protoPath = filepath.Join(g.sdkPath, "proto") + protoPath = filepath.Join(g.sdkDir, "proto") } else { // Check that the app/package proto directory exists protoPath = filepath.Join(path, g.protoDir) diff --git a/ignite/pkg/cosmosgen/generate_typescript.go b/ignite/pkg/cosmosgen/generate_typescript.go index cfc8726ea7..80ecd12997 100644 --- a/ignite/pkg/cosmosgen/generate_typescript.go +++ b/ignite/pkg/cosmosgen/generate_typescript.go @@ -200,7 +200,7 @@ func (g *tsGenerator) generateModuleTemplate( // proto path which is where the proto files are stored. var pp string if module.IsCosmosSDKModulePkg(appPath) { - pp = filepath.Join(g.g.sdkPath, "proto") + pp = filepath.Join(g.g.sdkDir, "proto") } else { pp = filepath.Join(appPath, g.g.protoDir) } From 4bb2cea411c614449a4872e9b1864497e1deb27f Mon Sep 17 00:00:00 2001 From: Clockwork Date: Mon, 4 Dec 2023 11:43:57 +0200 Subject: [PATCH 17/17] fix: Update package.json template --- ignite/pkg/cosmosgen/templates/root/package.json.tpl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ignite/pkg/cosmosgen/templates/root/package.json.tpl b/ignite/pkg/cosmosgen/templates/root/package.json.tpl index 8cd8cdea6b..b0babc1b29 100644 --- a/ignite/pkg/cosmosgen/templates/root/package.json.tpl +++ b/ignite/pkg/cosmosgen/templates/root/package.json.tpl @@ -15,8 +15,7 @@ "access": "public" }, "scripts": { - "build": "NODE_OPTIONS='--max-old-space-size=16384' tsc", - "postinstall": "npm run build" + "build": "NODE_OPTIONS='--max-old-space-size=16384' tsc" }, "dependencies": { "@cosmjs/proto-signing": "0.31.1",