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
15 changes: 14 additions & 1 deletion cmd/plugins/plugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -41,3 +42,15 @@ 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:
git:
enabled: true
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
4 changes: 2 additions & 2 deletions plugin/adapters/plugin/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
75 changes: 65 additions & 10 deletions plugin/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"

"gopkg.in/yaml.v2"
Expand All @@ -20,11 +21,18 @@ 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 {
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"`
}
Expand Down Expand Up @@ -53,14 +61,61 @@ 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 == "" {
continue
}

if pl.WorkDir.Git.Enabled {
path := filepath.Join(os.TempDir(), pl.ID)
remote := pl.WorkDir.Path

needClone := true
if pl.WorkDir.Git.Persistent {
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 needClone {
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
}

if !filepath.IsAbs(pl.WorkDir.Path) {
pl.WorkDir.Path = filepath.Clean(pl.WorkDir.Path)
}
}
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()
}