Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions cmd/spawn/local-interchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package main

import (
"os"
"os/exec"
"path"

"github.com/spf13/cobra"

Expand All @@ -16,6 +14,7 @@ const (

func init() {
LocalICCmd.Flags().Bool(FlagLocationPath, false, "print the location of local-ic binary")

}

// ---
Expand All @@ -34,12 +33,7 @@ var LocalICCmd = &cobra.Command{

logger := GetLogger()

loc := whereIsLocalICInstalled()
if loc == "" {
logger.Error("local-ic not found. Please run `make get-localic`")
return
}

loc := spawn.WhereIsBinInstalled("local-ic")
if debugBinaryLoc {
logger.Debug("local-ic binary", "location", loc)
return
Expand All @@ -61,17 +55,3 @@ var LocalICCmd = &cobra.Command{
}
},
}

func whereIsLocalICInstalled() string {
for _, path := range []string{"local-ic", path.Join("bin", "local-ic"), path.Join("local-interchain", "localic")} {
if _, err := os.Stat(path); err == nil {
return path
}
}

if path, err := exec.LookPath("local-ic"); err == nil {
return path
}

return ""
}
165 changes: 50 additions & 115 deletions cmd/spawn/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,51 @@ package main

import (
"fmt"
"io/fs"
"log"
"log/slog"
"os"
"os/exec"
"path"
"strings"
"time"

"github.com/lmittmann/tint"
"github.com/mattn/go-isatty"
"github.com/rollchains/spawn/spawn"
"github.com/spf13/cobra"
)

// Set in the makefile ld_flags on compile
var SpawnVersion = ""

var LogLevelFlag = "log-level"
var (
// Set in the makefile ld_flags on compile
SpawnVersion = ""
LogLevelFlag = "log-level"
rootCmd = &cobra.Command{
Use: "spawn",
Short: "Entry into the Interchain | Contact us: support@rollchains.com",
CompletionOptions: cobra.CompletionOptions{
HiddenDefaultCmd: false,
},
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Fatal(err)
}
},
}
)

func main() {
outOfDateChecker()

rootCmd.AddCommand(newChain)
rootCmd.AddCommand(LocalICCmd)
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Print the version number of spawn",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(SpawnVersion)
},
})
rootCmd.AddCommand(ModuleCmd())
rootCmd.AddCommand(ProtoServiceGenerate())
rootCmd.AddCommand(DocsCmd)
rootCmd.AddCommand(contactCmd)

applyPluginCmds()

Expand Down Expand Up @@ -59,123 +76,41 @@ func GetLogger() *slog.Logger {
return slog.Default()
}

var PluginsCmd = &cobra.Command{
Use: "plugins",
Short: "Spawn Plugins",
Aliases: []string{"plugin", "plug", "pl"},
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Fatal(err)
}
},
}
// outOfDateChecker checks if binaries are up to date and logs if they are not.
// if not, it will prompt the user every command they run with spawn until they update.
// else, it will wait 24h+ before checking again.
func outOfDateChecker() {
logger := GetLogger()

func applyPluginCmds() {
for name, abspath := range loadPlugins() {
name := name
abspath := abspath
if !spawn.DoOutdatedNotificationRunCheck(logger) {
return
}

info, err := ParseCobraCLICmd(abspath)
for _, program := range []string{"local-ic", "spawn"} {
releases, err := spawn.GetLatestGithubReleases(spawn.BinaryToGithubAPI[program])
if err != nil {
GetLogger().Warn("error parsing the CLI commands from the plugin", "name", name, "error", err)
continue
logger.Error("Error getting latest local-ic releases", "err", err)
return
}
latest := releases[0].TagName

execCmd := &cobra.Command{
Use: name,
Short: info.Description,
Run: func(cmd *cobra.Command, args []string) {
output, err := exec.Command(abspath, args...).CombinedOutput()
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(string(output))
},
}
PluginsCmd.AddCommand(execCmd)
}

rootCmd.AddCommand(PluginsCmd)
}

// returns name and path
func loadPlugins() map[string]string {
p := make(map[string]string)

logger := GetLogger()

homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}

pluginsDir := path.Join(homeDir, ".spawn", "plugins")
current := spawn.GetLocalVersion(logger, program, latest)
if spawn.OutOfDateCheckLog(logger, program, current, latest) {
// write check to -24h from now to spam the user until it's resolved.

d := os.DirFS(pluginsDir)
if _, err := d.Open("."); err != nil {
if os.IsNotExist(err) {
if err := os.MkdirAll(pluginsDir, 0755); err != nil {
panic(err)
file, err := spawn.GetLatestVersionCheckFile(logger)
if err != nil {
return
}
} else {
panic(err)
}
}

err = fs.WalkDir(d, ".", func(relPath string, d fs.DirEntry, e error) error {
if d.IsDir() {
return nil
}

// /home/username/.spawn/plugins/myplugin
absPath := path.Join(pluginsDir, relPath)
if err := spawn.WriteLastTimeToFile(logger, file, time.Now().Add(-spawn.RunCheckInterval)); err != nil {
logger.Error("Error writing last check file", "err", err)
return
}

// ensure path exist
if _, err := os.Stat(absPath); os.IsNotExist(err) {
logger.Error(fmt.Sprintf("Plugin %s does not exist. Skipping", absPath))
return nil
return
}

name := path.Base(absPath)
p[name] = absPath
return nil
})
if err != nil {
logger.Error(fmt.Sprintf("Error walking the path %s: %v", pluginsDir, err))
panic(err)
}

return p
}

var rootCmd = &cobra.Command{
Use: "spawn",
Short: "Entry into the Interchain",
CompletionOptions: cobra.CompletionOptions{
HiddenDefaultCmd: false,
},
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Fatal(err)
}
},
}

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of spawn",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(SpawnVersion)
},
}

var contactCmd = &cobra.Command{
Use: "email",
Aliases: []string{"contact"},
Short: "Reach out and connect with us!",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Email us! support@rollchains.com")
},
}

func parseLogLevelFromFlags() slog.Level {
Expand Down
5 changes: 3 additions & 2 deletions cmd/spawn/new_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func TestDisabledGeneration(t *testing.T) {
}

// custom cases
// NOTE: block-explorer is disabled for all cases.
disabledCases := []disabledCase{
{
// by default ICS is used
Expand Down Expand Up @@ -70,14 +71,14 @@ func TestDisabledGeneration(t *testing.T) {

disabledCases = append(disabledCases, disabledCase{
Name: normalizedName,
Disabled: []string{f},
Disabled: []string{f, spawn.BlockExplorer},
})
}

for _, c := range disabledCases {
c := c
name := "spawnunittest" + c.Name
dc := c.Disabled
dc := append(c.Disabled, spawn.BlockExplorer)

fmt.Println("=====\ndisabled cases", name, dc)

Expand Down
101 changes: 101 additions & 0 deletions cmd/spawn/plugins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package main

import (
"fmt"
"io/fs"
"log"
"os"
"os/exec"
"path"

"github.com/spf13/cobra"
)

var PluginsCmd = &cobra.Command{
Use: "plugins",
Short: "Spawn Plugins",
Aliases: []string{"plugin", "plug", "pl"},
Run: func(cmd *cobra.Command, args []string) {
if err := cmd.Help(); err != nil {
log.Fatal(err)
}
},
}

func applyPluginCmds() {
for name, abspath := range loadPlugins() {
name := name
abspath := abspath

info, err := ParseCobraCLICmd(abspath)
if err != nil {
GetLogger().Warn("error parsing the CLI commands from the plugin", "name", name, "error", err)
continue
}

execCmd := &cobra.Command{
Use: name,
Short: info.Description,
Run: func(cmd *cobra.Command, args []string) {
output, err := exec.Command(abspath, args...).CombinedOutput()
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(string(output))
},
}
PluginsCmd.AddCommand(execCmd)
}

rootCmd.AddCommand(PluginsCmd)
}

// returns name and path
func loadPlugins() map[string]string {
p := make(map[string]string)

logger := GetLogger()

homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}

pluginsDir := path.Join(homeDir, ".spawn", "plugins")

d := os.DirFS(pluginsDir)
if _, err := d.Open("."); err != nil {
if os.IsNotExist(err) {
if err := os.MkdirAll(pluginsDir, 0755); err != nil {
panic(err)
}
} else {
panic(err)
}
}

err = fs.WalkDir(d, ".", func(relPath string, d fs.DirEntry, e error) error {
if d.IsDir() {
return nil
}

// /home/username/.spawn/plugins/myplugin
absPath := path.Join(pluginsDir, relPath)

// ensure path exist
if _, err := os.Stat(absPath); os.IsNotExist(err) {
logger.Error(fmt.Sprintf("Plugin %s does not exist. Skipping", absPath))
return nil
}

name := path.Base(absPath)
p[name] = absPath
return nil
})
if err != nil {
logger.Error(fmt.Sprintf("Error walking the path %s: %v", pluginsDir, err))
panic(err)
}

return p
}
5 changes: 5 additions & 0 deletions spawn/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ func ExecCommand(command string, args ...string) error {
return cmd.Run()
}

func ExecCommandWithOutput(command string, args ...string) ([]byte, error) {
cmd := exec.Command(command, args...)
return cmd.CombinedOutput()
}

func (cfg *NewChainConfig) GitInitNewProjectRepo() {
if err := ExecCommand("git", "init", cfg.ProjectName, "--quiet"); err != nil {
cfg.Logger.Error("Error initializing git", "err", err)
Expand Down
Loading