Skip to content
Open
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
1 change: 1 addition & 0 deletions internal/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func (m *Manager) createFile(

var buf bytes.Buffer
if err = tmpl.Execute(&buf, map[string]any{
"DevboxProjectDir": m.ProjectDir(),
"DevboxDir": filepath.Join(m.ProjectDir(), devboxDirName, name),
"DevboxDirRoot": filepath.Join(m.ProjectDir(), devboxDirName),
"DevboxProfileDefault": filepath.Join(m.ProjectDir(), nix.ProfilePath),
Expand Down
74 changes: 74 additions & 0 deletions internal/plugin/plugin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2024 Jetify Inc. and contributors. All rights reserved.
// Use of this source code is governed by the license in the LICENSE file.

package plugin

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// fakeIncludable is a minimal Includable used to exercise buildConfig's
// template-placeholder substitution without touching the filesystem or network.
type fakeIncludable struct {
name string
}

func (f fakeIncludable) CanonicalName() string { return f.name }
func (f fakeIncludable) FileContent(string) ([]byte, error) { return nil, nil }
func (f fakeIncludable) Hash() string { return "" }
func (f fakeIncludable) LockfileKey() string { return f.name }

// TestBuildConfigTemplatePlaceholders documents and locks in the meaning of the
// template placeholders available to plugins. In particular it guards against
// the confusion reported in #1987: DevboxDirRoot is the root of the devbox.d
// directory (not the project root), and DevboxProjectDir is the project root.
func TestBuildConfigTemplatePlaceholders(t *testing.T) {
projectDir := filepath.Join("/home", "user", "my-project")
const pluginName = "my-plugin"

content := `{
"name": "my-plugin",
"version": "0.0.1",
"create_files": {
"{{ .DevboxProjectDir }}/project-root": "a",
"{{ .DevboxDirRoot }}/dir-root": "b",
"{{ .DevboxDir }}/dir": "c",
"{{ .Virtenv }}/virtenv": "d"
}
}`

cfg, err := buildConfig(fakeIncludable{name: pluginName}, projectDir, content)
require.NoError(t, err)

// Invert the create_files map (contentPath -> renderedPath) so the
// assertions read naturally regardless of map ordering.
renderedByContent := map[string]string{}
for renderedPath, contentPath := range cfg.CreateFiles {
renderedByContent[contentPath] = renderedPath
}

assert.Equal(t,
filepath.Join(projectDir, "project-root"),
renderedByContent["a"],
"DevboxProjectDir should be the project root (where devbox.json lives)",
)
assert.Equal(t,
filepath.Join(projectDir, devboxDirName, "dir-root"),
renderedByContent["b"],
"DevboxDirRoot should be <projectDir>/devbox.d",
)
assert.Equal(t,
filepath.Join(projectDir, devboxDirName, pluginName, "dir"),
renderedByContent["c"],
"DevboxDir should be <projectDir>/devbox.d/<plugin.name>",
)
assert.Equal(t,
filepath.Join(projectDir, VirtenvPath, pluginName, "virtenv"),
renderedByContent["d"],
"Virtenv should be <projectDir>/.devbox/virtenv/<plugin.name>",
)
}
3 changes: 2 additions & 1 deletion plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ flowchart TD

Devbox's Plugin System provides a few special placeholders that should be used when specifying paths for env variables and helper files:

* `{{ .DevboxDirRoot }}` – points to the root folder of their project, where the user's `devbox.json` is stored.
* `{{ .DevboxProjectDir }}` – points to the root folder of the user's project, where their `devbox.json` is stored.
* `{{ .DevboxDirRoot }}` – points to `<projectDir>/devbox.d`, the shared parent directory of every plugin's `DevboxDir`. (Despite its name, this is *not* the project root — use `{{ .DevboxProjectDir }}` for that.)
* `{{ .DevboxDir }}` – points to `<projectDir>/devbox.d/<plugin.name>`. This directory is public and added to source control by default. This directory is not modified or recreated by Devbox after the initial package installation. You should use this location for files that a user will want to modify and check-in to source control alongside their project (e.g., `.conf` files or other configs).
* `{{ .Virtenv }}` – points to `<projectDir>/.devbox/virtenv/<plugin_name>` whenever the plugin activates. This directory is hidden and added to `.gitignore` by default You should use this location for files or variables that a user should not check-in or edit directly. Files in this directory should be considered managed by Devbox, and may be recreated or modified after the initial installation.

Expand Down
Loading