From cf7ff61cef57c0108c29b1ceafa5195d53677415 Mon Sep 17 00:00:00 2001 From: RestartFU Date: Sun, 23 Nov 2025 11:31:04 -0500 Subject: [PATCH 1/5] feat: implement remote git plugin support --- cmd/plugins/plugins.yaml | 11 +++++++- plugin/adapters/plugin/process.go | 4 +-- plugin/config/config.go | 44 ++++++++++++++++++++++++------- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/cmd/plugins/plugins.yaml b/cmd/plugins/plugins.yaml index a8b88e3..73f74d3 100644 --- a/cmd/plugins/plugins.yaml +++ b/cmd/plugins/plugins.yaml @@ -25,7 +25,8 @@ plugins: #args: ["../examples/plugins/typescript/dist/index.js"] command: "npm" args: ["run", "dev"] - work_dir: "../examples/plugins/typescript" + work_dir: + path: "../examples/plugins/typescript" env: NODE_ENV: production - id: example-php @@ -41,3 +42,11 @@ plugins: # - "--abort-on-container-exit" env: PHP_ENV: production + + - id: example-go + name: Example Go Plugin + command: "go" + args: ["run", "cmd/main.go"] + work_dir: + remote_git: true + path: https://github.com/secmc/plugin-go diff --git a/plugin/adapters/plugin/process.go b/plugin/adapters/plugin/process.go index 5611c98..783a2e2 100644 --- a/plugin/adapters/plugin/process.go +++ b/plugin/adapters/plugin/process.go @@ -110,8 +110,8 @@ func (p *pluginProcess) launchProcess(ctx context.Context, serverAddress string) } cmd := exec.CommandContext(ctx, p.cfg.Command, p.cfg.Args...) - if p.cfg.WorkDir != "" { - cmd.Dir = p.cfg.WorkDir + if p.cfg.WorkDir.Path != "" { + cmd.Dir = p.cfg.WorkDir.Path } env := os.Environ() env = append(env, fmt.Sprintf("DF_PLUGIN_ID=%s", p.id)) diff --git a/plugin/config/config.go b/plugin/config/config.go index 0cc61d5..5456e5d 100644 --- a/plugin/config/config.go +++ b/plugin/config/config.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "os/exec" "path/filepath" "gopkg.in/yaml.v2" @@ -20,11 +21,14 @@ type Config struct { } type PluginConfig struct { - ID string `yaml:"id"` - Name string `yaml:"name"` - Command string `yaml:"command"` - Args []string `yaml:"args"` - WorkDir string `yaml:"work_dir"` + ID string `yaml:"id"` + Name string `yaml:"name"` + Command string `yaml:"command"` + Args []string `yaml:"args"` + WorkDir struct { + RemoteGit bool `yaml:"remote_git"` + Path string `yaml:"path"` + } `yaml:"work_dir"` Env map[string]string `yaml:"env"` Address string `yaml:"address"` } @@ -53,12 +57,32 @@ func LoadConfig(path string) (Config, error) { cfg.HelloTimeoutMs = 2000 } for i := range cfg.Plugins { - if cfg.Plugins[i].ID == "" { - cfg.Plugins[i].ID = fmt.Sprintf("plugin-%d", i+1) + pl := &cfg.Plugins[i] + if pl.ID == "" { + pl.ID = fmt.Sprintf("plugin-%d", i+1) } - if cfg.Plugins[i].Command != "" && cfg.Plugins[i].WorkDir != "" { - if !filepath.IsAbs(cfg.Plugins[i].WorkDir) { - cfg.Plugins[i].WorkDir = filepath.Clean(cfg.Plugins[i].WorkDir) + if pl.Command != "" && pl.WorkDir.Path != "" { + if pl.WorkDir.RemoteGit { + path := "/tmp/" + pl.ID + err := os.RemoveAll(path) + if err != nil { + return cfg, err + } + + cmd := exec.Command("git", "clone", pl.WorkDir.Path, path, "--depth=1") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err = cmd.Run() + if err != nil { + return cfg, err + } + + pl.WorkDir.Path = path + } + + if !filepath.IsAbs(pl.WorkDir.Path) { + pl.WorkDir.Path = filepath.Clean(pl.WorkDir.Path) } } } From 940722fcda051529b37d8b540d0e796ffbc1bfaf Mon Sep 17 00:00:00 2001 From: RestartFU Date: Sun, 23 Nov 2025 11:47:45 -0500 Subject: [PATCH 2/5] add persistent option --- cmd/plugins/plugins.yaml | 1 + plugin/config/config.go | 55 ++++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/cmd/plugins/plugins.yaml b/cmd/plugins/plugins.yaml index 73f74d3..09b14d2 100644 --- a/cmd/plugins/plugins.yaml +++ b/cmd/plugins/plugins.yaml @@ -49,4 +49,5 @@ plugins: args: ["run", "cmd/main.go"] work_dir: remote_git: true + remote_persistent: true path: https://github.com/secmc/plugin-go diff --git a/plugin/config/config.go b/plugin/config/config.go index 5456e5d..0b6f246 100644 --- a/plugin/config/config.go +++ b/plugin/config/config.go @@ -26,8 +26,11 @@ type PluginConfig struct { Command string `yaml:"command"` Args []string `yaml:"args"` WorkDir struct { - RemoteGit bool `yaml:"remote_git"` - Path string `yaml:"path"` + RemoteGit bool `yaml:"remote_git"` + // RemotePersistent is used to choose whether or not to clone the remote git + // plugin on every startup + RemotePersistent bool `yaml:"remote_persistent"` + Path string `yaml:"path"` } `yaml:"work_dir"` Env map[string]string `yaml:"env"` Address string `yaml:"address"` @@ -61,29 +64,49 @@ func LoadConfig(path string) (Config, error) { if pl.ID == "" { pl.ID = fmt.Sprintf("plugin-%d", i+1) } - if pl.Command != "" && pl.WorkDir.Path != "" { - if pl.WorkDir.RemoteGit { - path := "/tmp/" + pl.ID - err := os.RemoveAll(path) - if err != nil { - return cfg, err - } + if pl.Command == "" || pl.WorkDir.Path == "" { + continue + } + + if pl.WorkDir.RemoteGit { + path := filepath.Join(os.TempDir(), pl.ID) + remote := pl.WorkDir.Path - cmd := exec.Command("git", "clone", pl.WorkDir.Path, path, "--depth=1") + clone := func() error { + cmd := exec.Command("git", "clone", remote, path, "--depth=1") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - return cfg, err + if err := cmd.Run(); err != nil { + return err } + return nil + } - pl.WorkDir.Path = path + needClone := true + if pl.WorkDir.RemotePersistent { + if _, err := os.Stat(path); err == nil { + needClone = false + } else if !errors.Is(err, os.ErrNotExist) { + return cfg, fmt.Errorf("stat remote plugin %q: %w", pl.ID, err) + } + } else { + if err := os.RemoveAll(path); err != nil { + return cfg, fmt.Errorf("reset remote plugin %q: %w", pl.ID, err) + } } - if !filepath.IsAbs(pl.WorkDir.Path) { - pl.WorkDir.Path = filepath.Clean(pl.WorkDir.Path) + if needClone { + if err := clone(); err != nil { + return cfg, fmt.Errorf("clone remote plugin %q: %w", pl.ID, err) + } } + + pl.WorkDir.Path = path + } + + if !filepath.IsAbs(pl.WorkDir.Path) { + pl.WorkDir.Path = filepath.Clean(pl.WorkDir.Path) } } return cfg, nil From d38e562c0640d27918ae242749a8094cdc9b9cff Mon Sep 17 00:00:00 2001 From: RestartFU Date: Sun, 23 Nov 2025 11:48:58 -0500 Subject: [PATCH 3/5] various changes --- plugin/config/config.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugin/config/config.go b/plugin/config/config.go index 0b6f246..52cd1e0 100644 --- a/plugin/config/config.go +++ b/plugin/config/config.go @@ -77,10 +77,7 @@ func LoadConfig(path string) (Config, error) { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return err - } - return nil + return cmd.Run() } needClone := true From 1bc3dbf971b5918a00252eb5a27196bffd4bdf73 Mon Sep 17 00:00:00 2001 From: RestartFU Date: Sun, 23 Nov 2025 12:09:33 -0500 Subject: [PATCH 4/5] various changes --- cmd/plugins/plugins.yaml | 6 ++++-- plugin/config/config.go | 43 +++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/cmd/plugins/plugins.yaml b/cmd/plugins/plugins.yaml index 09b14d2..a64bc95 100644 --- a/cmd/plugins/plugins.yaml +++ b/cmd/plugins/plugins.yaml @@ -48,6 +48,8 @@ plugins: command: "go" args: ["run", "cmd/main.go"] work_dir: - remote_git: true - remote_persistent: true + git: + enabled: true + #persistent: true + version: tags/v0.0.1 path: https://github.com/secmc/plugin-go diff --git a/plugin/config/config.go b/plugin/config/config.go index 52cd1e0..d811be2 100644 --- a/plugin/config/config.go +++ b/plugin/config/config.go @@ -26,11 +26,12 @@ type PluginConfig struct { Command string `yaml:"command"` Args []string `yaml:"args"` WorkDir struct { - RemoteGit bool `yaml:"remote_git"` - // RemotePersistent is used to choose whether or not to clone the remote git - // plugin on every startup - RemotePersistent bool `yaml:"remote_persistent"` - Path string `yaml:"path"` + Git struct { + Enabled bool `yaml:"enabled"` + Persistent bool `yaml:"persistent"` + Version string `yaml:"version"` + } `yaml:"git"` + Path string `yaml:"path"` } `yaml:"work_dir"` Env map[string]string `yaml:"env"` Address string `yaml:"address"` @@ -68,20 +69,12 @@ func LoadConfig(path string) (Config, error) { continue } - if pl.WorkDir.RemoteGit { + if pl.WorkDir.Git.Enabled { path := filepath.Join(os.TempDir(), pl.ID) remote := pl.WorkDir.Path - clone := func() error { - cmd := exec.Command("git", "clone", remote, path, "--depth=1") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - return cmd.Run() - } - needClone := true - if pl.WorkDir.RemotePersistent { + if pl.WorkDir.Git.Persistent { if _, err := os.Stat(path); err == nil { needClone = false } else if !errors.Is(err, os.ErrNotExist) { @@ -94,9 +87,15 @@ func LoadConfig(path string) (Config, error) { } if needClone { - if err := clone(); err != nil { + if err := run("git", "", "clone", remote, path, "--depth=1"); err != nil { return cfg, fmt.Errorf("clone remote plugin %q: %w", pl.ID, err) } + + if pl.WorkDir.Git.Version != "" { + if err := run("git", path, "checkout", "--detach", pl.WorkDir.Git.Version); err != nil { + return cfg, err + } + } } pl.WorkDir.Path = path @@ -108,3 +107,15 @@ func LoadConfig(path string) (Config, error) { } return cfg, nil } + +func run(bin string, path string, args ...string) error { + cmd := exec.Command(bin, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if path != "" { + cmd.Dir = path + } + + return cmd.Run() +} From 6553bab7cf7ceaa2a351b4428064a8b5efa7d9c1 Mon Sep 17 00:00:00 2001 From: RestartFU Date: Sun, 23 Nov 2025 12:11:21 -0500 Subject: [PATCH 5/5] various changes --- cmd/plugins/plugins.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/plugins/plugins.yaml b/cmd/plugins/plugins.yaml index a64bc95..4b379e8 100644 --- a/cmd/plugins/plugins.yaml +++ b/cmd/plugins/plugins.yaml @@ -50,6 +50,7 @@ plugins: work_dir: git: enabled: true - #persistent: true - version: tags/v0.0.1 + persistent: false # persistent can be set to true if you don't + # want the plugin to be cloned at every startup + version: tags/v0.0.1 # can also specify commit hashes path: https://github.com/secmc/plugin-go