From 685f5cee9cd1a7dad9cc719ac4a44f73589d3e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hubert?= Date: Sat, 25 Oct 2025 09:59:27 +0200 Subject: [PATCH 1/2] introduce git plugin --- internal/plugin/files.go | 6 + internal/plugin/git.go | 165 ++++++++++++++++ internal/plugin/git_test.go | 343 ++++++++++++++++++++++++++++++++++ internal/plugin/includable.go | 2 + 4 files changed, 516 insertions(+) create mode 100644 internal/plugin/git.go create mode 100644 internal/plugin/git_test.go diff --git a/internal/plugin/files.go b/internal/plugin/files.go index 7bbef21e1d8..1a0d2269a83 100644 --- a/internal/plugin/files.go +++ b/internal/plugin/files.go @@ -24,6 +24,12 @@ func getConfigIfAny(inc Includable, projectDir string) (*Config, error) { return nil, errors.WithStack(err) } return buildConfig(includable, projectDir, string(content)) + case *gitPlugin: + content, err := includable.Fetch() + if err != nil { + return nil, errors.WithStack(err) + } + return buildConfig(includable, projectDir, string(content)) case *LocalPlugin: content, err := os.ReadFile(includable.Path()) if err != nil && !os.IsNotExist(err) { diff --git a/internal/plugin/git.go b/internal/plugin/git.go new file mode 100644 index 00000000000..567cee4ab44 --- /dev/null +++ b/internal/plugin/git.go @@ -0,0 +1,165 @@ +// 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 ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "go.jetify.com/devbox/nix/flake" +) + +type gitPlugin struct { + ref *flake.Ref + name string +} + +// newGitPlugin creates a Git plugin from a flake reference. +// It uses git clone to fetch the repository. +func newGitPlugin(ref flake.Ref) (*gitPlugin, error) { + if ref.Type != flake.TypeGit { + return nil, fmt.Errorf("expected git flake reference, got %s", ref.Type) + } + + name := generateGitPluginName(ref) + + return &gitPlugin{ + ref: &ref, + name: name, + }, nil +} + +func generateGitPluginName(ref flake.Ref) string { + // Extract repository name from URL and append directory if specified + url := ref.URL + if url == "" { + return "unknown.git" + } + + // Remove query parameters to get clean URL + if strings.Contains(url, "?") { + url = strings.Split(url, "?")[0] + } + + url = strings.TrimSuffix(url, ".git") + + parts := strings.Split(url, "/") + if len(parts) < 2 { + return "unknown.git" + } + + // Use last two path components (e.g., "owner/repo") + repoParts := parts[len(parts)-2:] + + name := strings.Join(repoParts, ".") + name = strings.ReplaceAll(name, "/", ".") + + // Append directory to make name unique when multiple plugins + // from same repo are used + if ref.Dir != "" { + dirName := strings.ReplaceAll(ref.Dir, "/", ".") + name = name + "." + dirName + } + + return name +} + +// getBaseURL extracts the base Git URL without query parameters. +// Query parameters like ?dir=path are used by Nix flakes but not by git clone. +func (p *gitPlugin) getBaseURL() string { + baseURL := p.ref.URL + if strings.Contains(baseURL, "?") { + baseURL = strings.Split(baseURL, "?")[0] + } + return baseURL +} + +func (p *gitPlugin) Fetch() ([]byte, error) { + content, err := p.FileContent("plugin.json") + if err != nil { + return nil, err + } + return content, nil +} + +func (p *gitPlugin) cloneAndRead(subpath string) ([]byte, error) { + tempDir, err := os.MkdirTemp("", "devbox-git-plugin-*") + if err != nil { + return nil, fmt.Errorf("failed to create temp directory: %w", err) + } + defer os.RemoveAll(tempDir) + + // Clone repository using base URL without query parameters + baseURL := p.getBaseURL() + + cloneCmd := exec.Command("git", "clone", "--depth", "1", baseURL, tempDir) + if p.ref.Rev != "" { + cloneCmd = exec.Command("git", "clone", "--depth", "1", "--branch", p.ref.Rev, baseURL, tempDir) + } + + output, err := cloneCmd.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("failed to clone repository %s: %w\nOutput: %s", p.ref.URL, err, string(output)) + } + + // Checkout specific commit if revision is a commit hash + if p.ref.Rev != "" && !isBranchName(p.ref.Rev) { + checkoutCmd := exec.Command("git", "checkout", p.ref.Rev) + checkoutCmd.Dir = tempDir + output, err := checkoutCmd.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("failed to checkout revision %s: %w\nOutput: %s", p.ref.Rev, err, string(output)) + } + } + + // Read file from repository root or specified directory + filePath := filepath.Join(tempDir, subpath) + if p.ref.Dir != "" { + filePath = filepath.Join(tempDir, p.ref.Dir, subpath) + } + + content, err := os.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("failed to read file %s: %w", filePath, err) + } + + return content, nil +} + +func isBranchName(ref string) bool { + // Full commit hashes are 40 hex characters + if len(ref) == 40 { + for _, c := range ref { + if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { + return true + } + } + return false + } + return true +} + +func (p *gitPlugin) CanonicalName() string { + return p.name +} + +// Hash returns a unique hash for this plugin including directory. +// This ensures plugins from the same repo with different dirs are unique. +func (p *gitPlugin) Hash() string { + if p.ref.Dir != "" { + return fmt.Sprintf("%s-%s-%s", p.ref.URL, p.ref.Rev, p.ref.Dir) + } + return fmt.Sprintf("%s-%s", p.ref.URL, p.ref.Rev) +} + +func (p *gitPlugin) FileContent(subpath string) ([]byte, error) { + return p.cloneAndRead(subpath) +} + +func (p *gitPlugin) LockfileKey() string { + return p.ref.String() +} diff --git a/internal/plugin/git_test.go b/internal/plugin/git_test.go new file mode 100644 index 00000000000..ea52ad532c5 --- /dev/null +++ b/internal/plugin/git_test.go @@ -0,0 +1,343 @@ +// 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 ( + "testing" + + "go.jetify.com/devbox/nix/flake" +) + +func TestGitPlugin(t *testing.T) { + tests := []struct { + name string + ref string + expected *gitPlugin + }{ + { + name: "basic git plugin", + ref: "git+https://github.com/jetify-com/devbox-plugins.git", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://github.com/jetify-com/devbox-plugins.git", + }, + name: "jetify-com.devbox-plugins", + }, + }, + { + name: "git plugin with ref", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?ref=main", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://github.com/jetify-com/devbox-plugins.git", + Ref: "main", + }, + name: "jetify-com.devbox-plugins", + }, + }, + { + name: "git plugin with rev", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?rev=abc123", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://github.com/jetify-com/devbox-plugins.git", + Rev: "abc123", + }, + name: "jetify-com.devbox-plugins", + }, + }, + { + name: "git plugin with directory", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?dir=mongodb", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://github.com/jetify-com/devbox-plugins.git?dir=mongodb", + Dir: "mongodb", + }, + name: "jetify-com.devbox-plugins.mongodb", + }, + }, + { + name: "git plugin with directory and ref", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?dir=mongodb&ref=my-branch", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://github.com/jetify-com/devbox-plugins.git?dir=mongodb", + Dir: "mongodb", + Ref: "my-branch", + }, + name: "jetify-com.devbox-plugins.mongodb", + }, + }, + { + name: "git plugin with subgroups", + ref: "git+https://gitlab.com/group/subgroup/repo.git", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "https://gitlab.com/group/subgroup/repo.git", + }, + name: "subgroup.repo", + }, + }, + { + name: "git plugin with SSH URL", + ref: "git+ssh://git@github.com/jetify-com/devbox-plugins.git", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "ssh://git@github.com/jetify-com/devbox-plugins.git", + }, + name: "jetify-com.devbox-plugins", + }, + }, + { + name: "git plugin with file URL", + ref: "git+file:///tmp/local-repo.git", + expected: &gitPlugin{ + ref: &flake.Ref{ + Type: flake.TypeGit, + URL: "file:///tmp/local-repo.git", + }, + name: "tmp.local-repo", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ref, err := flake.ParseRef(tt.ref) + if err != nil { + t.Fatalf("Failed to parse ref %q: %v", tt.ref, err) + } + + plugin, err := newGitPlugin(ref) + if err != nil { + t.Fatalf("Failed to create Git plugin: %v", err) + } + + if plugin.ref.Type != tt.expected.ref.Type { + t.Errorf("Expected type %q, got %q", tt.expected.ref.Type, plugin.ref.Type) + } + if plugin.ref.URL != tt.expected.ref.URL { + t.Errorf("Expected URL %q, got %q", tt.expected.ref.URL, plugin.ref.URL) + } + if plugin.ref.Ref != tt.expected.ref.Ref { + t.Errorf("Expected ref %q, got %q", tt.expected.ref.Ref, plugin.ref.Ref) + } + if plugin.ref.Rev != tt.expected.ref.Rev { + t.Errorf("Expected rev %q, got %q", tt.expected.ref.Rev, plugin.ref.Rev) + } + if plugin.ref.Dir != tt.expected.ref.Dir { + t.Errorf("Expected dir %q, got %q", tt.expected.ref.Dir, plugin.ref.Dir) + } + if plugin.name != tt.expected.name { + t.Errorf("Expected name %q, got %q", tt.expected.name, plugin.name) + } + }) + } +} + +func TestGenerateGitPluginName(t *testing.T) { + tests := []struct { + name string + ref flake.Ref + expected string + }{ + { + name: "github repository", + ref: flake.Ref{ + URL: "https://github.com/jetify-com/devbox-plugins.git", + }, + expected: "jetify-com.devbox-plugins", + }, + { + name: "gitlab repository with subgroups", + ref: flake.Ref{ + URL: "https://gitlab.com/group/subgroup/repo.git", + }, + expected: "subgroup.repo", + }, + { + name: "repository without .git suffix", + ref: flake.Ref{ + URL: "https://github.com/jetify-com/devbox-plugins", + }, + expected: "jetify-com.devbox-plugins", + }, + { + name: "repository with single path component", + ref: flake.Ref{ + URL: "https://github.com/repo", + }, + expected: "github.com.repo", + }, + { + name: "SSH repository", + ref: flake.Ref{ + URL: "ssh://git@github.com/jetify-com/devbox-plugins.git", + }, + expected: "jetify-com.devbox-plugins", + }, + { + name: "file repository", + ref: flake.Ref{ + URL: "file:///tmp/local-repo.git", + }, + expected: "tmp.local-repo", + }, + { + name: "repository with directory", + ref: flake.Ref{ + URL: "https://github.com/jetify-com/devbox-plugins.git", + Dir: "mongodb", + }, + expected: "jetify-com.devbox-plugins.mongodb", + }, + { + name: "repository with nested directory", + ref: flake.Ref{ + URL: "https://github.com/jetify-com/devbox-plugins.git", + Dir: "plugins/python", + }, + expected: "jetify-com.devbox-plugins.plugins.python", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := generateGitPluginName(tt.ref) + if result != tt.expected { + t.Errorf("Expected name %q, got %q", tt.expected, result) + } + }) + } +} + +func TestGitPluginURL(t *testing.T) { + tests := []struct { + name string + ref string + subpath string + expected string + }{ + { + name: "basic plugin.json", + ref: "git+https://github.com/jetify-com/devbox-plugins.git", + subpath: "plugin.json", + expected: "plugin.json", + }, + { + name: "plugin with directory", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?dir=mongodb", + subpath: "plugin.json", + expected: "mongodb/plugin.json", + }, + { + name: "plugin with ref", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?ref=main", + subpath: "plugin.json", + expected: "plugin.json", + }, + { + name: "plugin with directory and ref", + ref: "git+https://github.com/jetify-com/devbox-plugins.git?dir=mongodb&ref=my-branch", + subpath: "plugin.json", + expected: "mongodb/plugin.json", + }, + { + name: "plugin with subgroups", + ref: "git+https://gitlab.com/group/subgroup/repo.git", + subpath: "plugin.json", + expected: "plugin.json", + }, + { + name: "plugin with SSH URL", + ref: "git+ssh://git@github.com/jetify-com/devbox-plugins.git", + subpath: "plugin.json", + expected: "plugin.json", + }, + { + name: "plugin with file URL", + ref: "git+file:///tmp/local-repo.git", + subpath: "plugin.json", + expected: "plugin.json", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ref, err := flake.ParseRef(tt.ref) + if err != nil { + t.Fatalf("Failed to parse ref %q: %v", tt.ref, err) + } + + plugin, err := newGitPlugin(ref) + if err != nil { + t.Fatalf("Failed to create Git plugin: %v", err) + } + + // Test that the plugin can be created and the subpath is handled correctly + // The actual file path will be constructed in FileContent method + if plugin.ref.Dir != "" { + expectedPath := plugin.ref.Dir + "/" + tt.subpath + if expectedPath != tt.expected { + t.Errorf("Expected path %q, got %q", tt.expected, expectedPath) + } + } else { + if tt.subpath != tt.expected { + t.Errorf("Expected subpath %q, got %q", tt.expected, tt.subpath) + } + } + }) + } +} + +func TestIsBranchName(t *testing.T) { + tests := []struct { + name string + ref string + expected bool + }{ + { + name: "branch name", + ref: "main", + expected: true, + }, + { + name: "branch name with slash", + ref: "feature/new-feature", + expected: true, + }, + { + name: "commit hash", + ref: "abc123def456", + expected: true, // Not 40 chars, so treated as branch + }, + { + name: "full commit hash", + ref: "a1b2c3d4e5f6789012345678901234567890abcd", + expected: false, // 40 chars, looks like commit hash + }, + { + name: "short commit hash", + ref: "abc123", + expected: true, // Not 40 chars, so treated as branch + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := isBranchName(tt.ref) + if result != tt.expected { + t.Errorf("Expected %v for %q, got %v", tt.expected, tt.ref, result) + } + }) + } +} diff --git a/internal/plugin/includable.go b/internal/plugin/includable.go index 84984e23551..480eb4de658 100644 --- a/internal/plugin/includable.go +++ b/internal/plugin/includable.go @@ -26,6 +26,8 @@ func parseIncludable(includableRef, workingDir string) (Includable, error) { return newLocalPlugin(ref, workingDir) case flake.TypeGitHub: return newGithubPlugin(ref) + case flake.TypeGit: + return newGitPlugin(ref) default: return nil, fmt.Errorf("unsupported ref type %q", ref.Type) } From 3ccb1fde0d7d5274d6098f55654d381592092390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hubert?= Date: Sat, 25 Oct 2025 11:06:20 +0200 Subject: [PATCH 2/2] add git examples --- .../some-file.txt | 1 + examples/plugins/git-with-revision/devbox.json | 16 ++++++++++++++++ examples/plugins/git-with-revision/devbox.lock | 4 ++++ examples/plugins/git-with-revision/test.sh | 9 +++++++++ .../some-file.txt | 1 + .../some-file.txt | 1 + examples/plugins/git/devbox.json | 18 ++++++++++++++++++ examples/plugins/git/devbox.lock | 4 ++++ examples/plugins/git/test.sh | 14 ++++++++++++++ .../some-file.txt | 1 + examples/plugins/v2-git/devbox.json | 17 +++++++++++++++++ examples/plugins/v2-git/devbox.lock | 4 ++++ examples/plugins/v2-git/test.sh | 11 +++++++++++ 13 files changed, 101 insertions(+) create mode 100644 examples/plugins/git-with-revision/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt create mode 100644 examples/plugins/git-with-revision/devbox.json create mode 100644 examples/plugins/git-with-revision/devbox.lock create mode 100755 examples/plugins/git-with-revision/test.sh create mode 100644 examples/plugins/git/devbox.d/jetify-com.devbox-plugin-example.my-github-plugin/some-file.txt create mode 100644 examples/plugins/git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt create mode 100644 examples/plugins/git/devbox.json create mode 100644 examples/plugins/git/devbox.lock create mode 100755 examples/plugins/git/test.sh create mode 100644 examples/plugins/v2-git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt create mode 100644 examples/plugins/v2-git/devbox.json create mode 100644 examples/plugins/v2-git/devbox.lock create mode 100755 examples/plugins/v2-git/test.sh diff --git a/examples/plugins/git-with-revision/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt b/examples/plugins/git-with-revision/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt new file mode 100644 index 00000000000..426863280ee --- /dev/null +++ b/examples/plugins/git-with-revision/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt @@ -0,0 +1 @@ +some data diff --git a/examples/plugins/git-with-revision/devbox.json b/examples/plugins/git-with-revision/devbox.json new file mode 100644 index 00000000000..9b1ad39ad33 --- /dev/null +++ b/examples/plugins/git-with-revision/devbox.json @@ -0,0 +1,16 @@ +{ + "packages": [], + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "run_test": [ + "./test.sh" + ] + } + }, + "include": [ + "git+ssh://git@github.com/jetify-com/devbox-plugin-example.git?rev=d9c00334353c9b1294c7bd5dbea128c149b2eb3a" + ] +} diff --git a/examples/plugins/git-with-revision/devbox.lock b/examples/plugins/git-with-revision/devbox.lock new file mode 100644 index 00000000000..4206f37d6b2 --- /dev/null +++ b/examples/plugins/git-with-revision/devbox.lock @@ -0,0 +1,4 @@ +{ + "lockfile_version": "1", + "packages": {} +} diff --git a/examples/plugins/git-with-revision/test.sh b/examples/plugins/git-with-revision/test.sh new file mode 100755 index 00000000000..7494f04f5b3 --- /dev/null +++ b/examples/plugins/git-with-revision/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +expected="I AM SET" +if [ "$MY_ENV_VAR" == "$expected" ]; then + echo "Success! MY_ENV_VAR is set to '$MY_ENV_VAR'" +else + echo "MY_ENV_VAR environment variable is not set to '$expected'" + exit 1 +fi diff --git a/examples/plugins/git/devbox.d/jetify-com.devbox-plugin-example.my-github-plugin/some-file.txt b/examples/plugins/git/devbox.d/jetify-com.devbox-plugin-example.my-github-plugin/some-file.txt new file mode 100644 index 00000000000..426863280ee --- /dev/null +++ b/examples/plugins/git/devbox.d/jetify-com.devbox-plugin-example.my-github-plugin/some-file.txt @@ -0,0 +1 @@ +some data diff --git a/examples/plugins/git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt b/examples/plugins/git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt new file mode 100644 index 00000000000..426863280ee --- /dev/null +++ b/examples/plugins/git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt @@ -0,0 +1 @@ +some data diff --git a/examples/plugins/git/devbox.json b/examples/plugins/git/devbox.json new file mode 100644 index 00000000000..42266a53437 --- /dev/null +++ b/examples/plugins/git/devbox.json @@ -0,0 +1,18 @@ +{ + "packages": [], + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "run_test": [ + "./test.sh" + ] + } + }, + "include": [ + "git+ssh://git@github.com/jetify-com/devbox-plugin-example.git", + "git+https://github.com/jetify-com/devbox-plugin-example.git?dir=custom-dir", + "git+https://github.com/jetify-com/devbox-plugin-example.git?ref=test/branch" + ] +} diff --git a/examples/plugins/git/devbox.lock b/examples/plugins/git/devbox.lock new file mode 100644 index 00000000000..4206f37d6b2 --- /dev/null +++ b/examples/plugins/git/devbox.lock @@ -0,0 +1,4 @@ +{ + "lockfile_version": "1", + "packages": {} +} diff --git a/examples/plugins/git/test.sh b/examples/plugins/git/test.sh new file mode 100755 index 00000000000..da2ed87f2da --- /dev/null +++ b/examples/plugins/git/test.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +expected="I AM SET (new value)" +custom_expected="I AM SET TO CUSTOM (new value)" +if [ "$MY_ENV_VAR" == "$expected" ] && [ "$MY_ENV_VAR_CUSTOM" == "$custom_expected" ]; then + echo "Success! MY_ENV_VAR is set to '$MY_ENV_VAR'" + echo "Success! MY_ENV_VAR_CUSTOM is set to '$MY_ENV_VAR_CUSTOM'" +else + echo "ERROR: MY_ENV_VAR environment variable is not set to '$expected' OR MY_ENV_VAR_CUSTOM variable is not set to '$custom_expected'" + exit 1 +fi + +echo BRANCH_ENV_VAR=$BRANCH_ENV_VAR +if [ "$BRANCH_ENV_VAR" != "I AM A BRANCH VAR" ]; then exit 1; fi; diff --git a/examples/plugins/v2-git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt b/examples/plugins/v2-git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt new file mode 100644 index 00000000000..426863280ee --- /dev/null +++ b/examples/plugins/v2-git/devbox.d/jetpack-io-devbox-plugin-example/some-file.txt @@ -0,0 +1 @@ +some data diff --git a/examples/plugins/v2-git/devbox.json b/examples/plugins/v2-git/devbox.json new file mode 100644 index 00000000000..d7884cb6d24 --- /dev/null +++ b/examples/plugins/v2-git/devbox.json @@ -0,0 +1,17 @@ +{ + "packages": [], + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "run_test": [ + "./test.sh" + ] + } + }, + "include": [ + "git+ssh://git@github.com/jetify-com/devbox-plugin-example.git", + "git+https://github.com/jetify-com/devbox-plugin-example?dir=custom-dir" + ] +} diff --git a/examples/plugins/v2-git/devbox.lock b/examples/plugins/v2-git/devbox.lock new file mode 100644 index 00000000000..4206f37d6b2 --- /dev/null +++ b/examples/plugins/v2-git/devbox.lock @@ -0,0 +1,4 @@ +{ + "lockfile_version": "1", + "packages": {} +} diff --git a/examples/plugins/v2-git/test.sh b/examples/plugins/v2-git/test.sh new file mode 100755 index 00000000000..2353ad15918 --- /dev/null +++ b/examples/plugins/v2-git/test.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +expected="I AM SET (new value)" +custom_expected="I AM SET TO CUSTOM (new value)" +if [ "$MY_ENV_VAR" == "$expected" ] && [ "$MY_ENV_VAR_CUSTOM" == "$custom_expected" ]; then + echo "Success! MY_ENV_VAR is set to '$MY_ENV_VAR'" + echo "Success! MY_ENV_VAR_CUSTOM is set to '$MY_ENV_VAR_CUSTOM'" +else + echo "ERROR: MY_ENV_VAR environment variable is not set to '$expected' OR MY_ENV_VAR_CUSTOM variable is not set to '$custom_expected'" + exit 1 +fi