Skip to content

Commit ffe6f63

Browse files
dncckRestartFU
andauthored
feat: implement remote git plugin support (#24)
* feat: implement remote git plugin support * add persistent option * various changes * various changes * various changes --------- Co-authored-by: RestartFU <me@restartfu.com>
1 parent 7db0cc9 commit ffe6f63

File tree

3 files changed

+81
-13
lines changed

3 files changed

+81
-13
lines changed

cmd/plugins/plugins.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ plugins:
2525
#args: ["../examples/plugins/typescript/dist/index.js"]
2626
command: "npm"
2727
args: ["run", "dev"]
28-
work_dir: "../examples/plugins/typescript"
28+
work_dir:
29+
path: "../examples/plugins/typescript"
2930
env:
3031
NODE_ENV: production
3132
- id: example-php
@@ -41,3 +42,15 @@ plugins:
4142
# - "--abort-on-container-exit"
4243
env:
4344
PHP_ENV: production
45+
46+
- id: example-go
47+
name: Example Go Plugin
48+
command: "go"
49+
args: ["run", "cmd/main.go"]
50+
work_dir:
51+
git:
52+
enabled: true
53+
persistent: false # persistent can be set to true if you don't
54+
# want the plugin to be cloned at every startup
55+
version: tags/v0.0.1 # can also specify commit hashes
56+
path: https://github.com/secmc/plugin-go

plugin/adapters/plugin/process.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ func (p *pluginProcess) launchProcess(ctx context.Context, serverAddress string)
110110
}
111111

112112
cmd := exec.CommandContext(ctx, p.cfg.Command, p.cfg.Args...)
113-
if p.cfg.WorkDir != "" {
114-
cmd.Dir = p.cfg.WorkDir
113+
if p.cfg.WorkDir.Path != "" {
114+
cmd.Dir = p.cfg.WorkDir.Path
115115
}
116116
env := os.Environ()
117117
env = append(env, fmt.Sprintf("DF_PLUGIN_ID=%s", p.id))

plugin/config/config.go

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"os/exec"
78
"path/filepath"
89

910
"gopkg.in/yaml.v2"
@@ -20,11 +21,18 @@ type Config struct {
2021
}
2122

2223
type PluginConfig struct {
23-
ID string `yaml:"id"`
24-
Name string `yaml:"name"`
25-
Command string `yaml:"command"`
26-
Args []string `yaml:"args"`
27-
WorkDir string `yaml:"work_dir"`
24+
ID string `yaml:"id"`
25+
Name string `yaml:"name"`
26+
Command string `yaml:"command"`
27+
Args []string `yaml:"args"`
28+
WorkDir struct {
29+
Git struct {
30+
Enabled bool `yaml:"enabled"`
31+
Persistent bool `yaml:"persistent"`
32+
Version string `yaml:"version"`
33+
} `yaml:"git"`
34+
Path string `yaml:"path"`
35+
} `yaml:"work_dir"`
2836
Env map[string]string `yaml:"env"`
2937
Address string `yaml:"address"`
3038
}
@@ -53,14 +61,61 @@ func LoadConfig(path string) (Config, error) {
5361
cfg.HelloTimeoutMs = 2000
5462
}
5563
for i := range cfg.Plugins {
56-
if cfg.Plugins[i].ID == "" {
57-
cfg.Plugins[i].ID = fmt.Sprintf("plugin-%d", i+1)
64+
pl := &cfg.Plugins[i]
65+
if pl.ID == "" {
66+
pl.ID = fmt.Sprintf("plugin-%d", i+1)
5867
}
59-
if cfg.Plugins[i].Command != "" && cfg.Plugins[i].WorkDir != "" {
60-
if !filepath.IsAbs(cfg.Plugins[i].WorkDir) {
61-
cfg.Plugins[i].WorkDir = filepath.Clean(cfg.Plugins[i].WorkDir)
68+
if pl.Command == "" || pl.WorkDir.Path == "" {
69+
continue
70+
}
71+
72+
if pl.WorkDir.Git.Enabled {
73+
path := filepath.Join(os.TempDir(), pl.ID)
74+
remote := pl.WorkDir.Path
75+
76+
needClone := true
77+
if pl.WorkDir.Git.Persistent {
78+
if _, err := os.Stat(path); err == nil {
79+
needClone = false
80+
} else if !errors.Is(err, os.ErrNotExist) {
81+
return cfg, fmt.Errorf("stat remote plugin %q: %w", pl.ID, err)
82+
}
83+
} else {
84+
if err := os.RemoveAll(path); err != nil {
85+
return cfg, fmt.Errorf("reset remote plugin %q: %w", pl.ID, err)
86+
}
6287
}
88+
89+
if needClone {
90+
if err := run("git", "", "clone", remote, path, "--depth=1"); err != nil {
91+
return cfg, fmt.Errorf("clone remote plugin %q: %w", pl.ID, err)
92+
}
93+
94+
if pl.WorkDir.Git.Version != "" {
95+
if err := run("git", path, "checkout", "--detach", pl.WorkDir.Git.Version); err != nil {
96+
return cfg, err
97+
}
98+
}
99+
}
100+
101+
pl.WorkDir.Path = path
102+
}
103+
104+
if !filepath.IsAbs(pl.WorkDir.Path) {
105+
pl.WorkDir.Path = filepath.Clean(pl.WorkDir.Path)
63106
}
64107
}
65108
return cfg, nil
66109
}
110+
111+
func run(bin string, path string, args ...string) error {
112+
cmd := exec.Command(bin, args...)
113+
cmd.Stdout = os.Stdout
114+
cmd.Stderr = os.Stderr
115+
116+
if path != "" {
117+
cmd.Dir = path
118+
}
119+
120+
return cmd.Run()
121+
}

0 commit comments

Comments
 (0)