Skip to content

Commit 6c833de

Browse files
authored
[plugins] Allow local non-compiled plugins (#1224)
## Summary This change allows users to add their own plugins using `devbox.json` `include` field (see example). It now supports all plugin fields (including services). Fixed: Issue where editing plugin would not be reflected. ## How was it tested? ```bash devbox run run_test -c examples/plugins/local MY_FOO_VAR is set to 'BAR' devbox services up ```
1 parent 0a280d1 commit 6c833de

File tree

13 files changed

+180
-25
lines changed

13 files changed

+180
-25
lines changed

devbox.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
"version": "1.52.2"
1818
}
1919
}
20-
}
20+
}

examples/plugins/local/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Custom plugin example
2+
3+
Shows how to write custom local plugin. Plugins can:
4+
5+
* Install packages
6+
* Create templatized files (including flakes)
7+
* Declare services (using process-compose)

examples/plugins/local/devbox.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"packages": [],
3+
"shell": {
4+
"init_hook": [
5+
"echo 'Welcome to devbox!' > /dev/null"
6+
],
7+
"scripts": {
8+
"run_test": [
9+
"./test.sh"
10+
]
11+
}
12+
},
13+
"include": [
14+
"path:my-plugin/my-plugin.json"
15+
]
16+
}

examples/plugins/local/devbox.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"lockfile_version": "1",
3+
"packages": {
4+
"path:my-plugin/my-plugin.json": {}
5+
}
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "my-plugin",
3+
"version": "0.0.1",
4+
"readme": "Example custom plugin",
5+
"env": {
6+
"MY_FOO_VAR": "BAR"
7+
},
8+
"create_files": {
9+
"{{ .Virtenv }}/empty-dir": "",
10+
"{{ .Virtenv }}/some-file": "some-file.txt",
11+
"{{ .Virtenv }}/process-compose.yaml": "process-compose.yaml"
12+
}
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: "0.5"
2+
3+
processes:
4+
my-plugin-service:
5+
command: echo "success" && tail -f /dev/null
6+
availability:
7+
restart: "always"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
some data

examples/plugins/local/test.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
if [ -z "$MY_FOO_VAR" ]; then
4+
echo "MY_FOO_VAR environment variable is not set."
5+
exit 1
6+
else
7+
echo "MY_FOO_VAR is set to '$MY_FOO_VAR'"
8+
fi

internal/impl/devbox.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,15 @@ func (d *Devbox) Config() *devconfig.Config {
127127
}
128128

129129
func (d *Devbox) ConfigHash() (string, error) {
130-
hashes := lo.Map(d.PackagesAsInputs(), func(i *devpkg.Package, _ int) string { return i.Hash() })
130+
pkgHashes := lo.Map(d.PackagesAsInputs(), func(i *devpkg.Package, _ int) string { return i.Hash() })
131+
includeHashes := lo.Map(d.Includes(), func(i plugin.Includable, _ int) string { return i.Hash() })
131132
h, err := d.cfg.Hash()
132133
if err != nil {
133134
return "", err
134135
}
135-
return cuecfg.Hash(h + strings.Join(hashes, ""))
136+
return cuecfg.Hash(
137+
h + strings.Join(pkgHashes, "") + strings.Join(includeHashes, ""),
138+
)
136139
}
137140

138141
func (d *Devbox) NixPkgsCommitHash() string {
@@ -919,6 +922,16 @@ func (d *Devbox) PackagesAsInputs() []*devpkg.Package {
919922
return devpkg.PackageFromStrings(d.Packages(), d.lockfile)
920923
}
921924

925+
func (d *Devbox) Includes() []plugin.Includable {
926+
includes := []plugin.Includable{}
927+
for _, includePath := range d.cfg.Include {
928+
if include, err := d.pluginManager.ParseInclude(includePath); err == nil {
929+
includes = append(includes, include)
930+
}
931+
}
932+
return includes
933+
}
934+
922935
func (d *Devbox) HasDeprecatedPackages() bool {
923936
for _, pkg := range d.PackagesAsInputs() {
924937
if pkg.IsLegacy() {

internal/plugin/files.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,28 @@
44
package plugin
55

66
import (
7+
"os"
78
"regexp"
89
"strings"
910

1011
"github.com/pkg/errors"
11-
"go.jetpack.io/devbox/internal/devpkg"
1212
"go.jetpack.io/devbox/plugins"
1313
)
1414

15-
func getConfigIfAny(pkg *devpkg.Package, projectDir string) (*config, error) {
15+
func getConfigIfAny(pkg Includable, projectDir string) (*config, error) {
1616
configFiles, err := plugins.BuiltIn.ReadDir(".")
1717
if err != nil {
1818
return nil, errors.WithStack(err)
1919
}
2020

21+
if local, ok := pkg.(*localPlugin); ok {
22+
content, err := os.ReadFile(local.path)
23+
if err != nil && !os.IsNotExist(err) {
24+
return nil, errors.WithStack(err)
25+
}
26+
return buildConfig(pkg, projectDir, string(content))
27+
}
28+
2129
for _, file := range configFiles {
2230
if file.IsDir() || strings.HasSuffix(file.Name(), ".go") {
2331
continue
@@ -44,6 +52,9 @@ func getConfigIfAny(pkg *devpkg.Package, projectDir string) (*config, error) {
4452
return nil, nil
4553
}
4654

47-
func getFileContent(contentPath string) ([]byte, error) {
55+
func getFileContent(pkg Includable, contentPath string) ([]byte, error) {
56+
if local, ok := pkg.(*localPlugin); ok {
57+
return os.ReadFile(local.contentPath(contentPath))
58+
}
4859
return plugins.BuiltIn.ReadFile(contentPath)
4960
}

0 commit comments

Comments
 (0)