Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
081f066
[BE-1876] Integrate nixpkgs plugin
marcell-vida Nov 11, 2025
eb05dd2
Check for version in index, remove plugin version pinning, fixes
marcell-vida Nov 11, 2025
1dfba3d
*
marcell-vida Nov 12, 2025
3738f29
Fix test version
marcell-vida Nov 12, 2025
ebe94d2
Rename tool
marcell-vida Nov 12, 2025
fce56eb
Remove index checking, use listing
marcell-vida Nov 12, 2025
d4c3efd
*
marcell-vida Nov 12, 2025
c177efe
Timeout on test
marcell-vida Nov 12, 2025
9aaccad
Simplify things
ofalvai Nov 13, 2025
95548fe
Get rid of MiseExecutor, make ExecEnv mockable instead
ofalvai Nov 14, 2025
adc95ec
Change plugin ID to final value
ofalvai Nov 14, 2025
24fd4b5
Unit tests
ofalvai Nov 14, 2025
aca4ce3
Add force flag for integration testing
ofalvai Nov 14, 2025
a2d8363
Integration tests
ofalvai Nov 14, 2025
972e50b
Add check before executing nix commands
ofalvai Nov 17, 2025
59c8133
Make feature flag value true instead of 1
ofalvai Nov 17, 2025
7e4bff6
AI reviewer fixes
marcell-vida Nov 18, 2025
945d3a3
Merge branch 'master' into BE-1876-integrate-nixpkgs-plugin
marcell-vida Nov 18, 2025
7d750f5
chore: trigger CI checks
marcell-vida Nov 18, 2025
d6e6b20
Raise timeout, install backend even with force install
marcell-vida Nov 18, 2025
67f994c
Lint
marcell-vida Nov 19, 2025
6f8f212
Fix tests, update plugin
marcell-vida Nov 19, 2025
488b138
Decrease validate timeout
marcell-vida Nov 19, 2025
45d52d4
Fix tests
marcell-vida Nov 19, 2025
dec4eb0
*
marcell-vida Nov 20, 2025
28bb814
Tests working on stable stacks too, consistent commenting
marcell-vida Nov 21, 2025
68e3e49
Remove nix availability check
marcell-vida Nov 21, 2025
e9574f3
Fake nix checking in tests instead of env var override
ofalvai Nov 24, 2025
ba0feab
Merge branch 'master' into BE-1876-integrate-nixpkgs-plugin
marcell-vida Nov 24, 2025
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
46 changes: 46 additions & 0 deletions integrationtests/toolprovider/mise/install_nixpkgs_ruby_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build linux_and_mac
// +build linux_and_mac

package mise

import (
"testing"

"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
"github.com/stretchr/testify/require"
)

func TestMiseInstallNixpkgsRuby(t *testing.T) {
tests := []struct {
name string
requestedVersion string
resolutionStrategy provider.ResolutionStrategy
expectedVersion string
}{
{"Install specific version", "3.3.9", provider.ResolutionStrategyStrict, "3.3.9"},
}

for _, tt := range tests {
miseInstallDir := t.TempDir()
miseDataDir := t.TempDir()
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
require.NoError(t, err)

err = miseProvider.Bootstrap()
require.NoError(t, err)

t.Run(tt.name, func(t *testing.T) {
request := provider.ToolRequest{
ToolName: "ruby",
UnparsedVersion: tt.requestedVersion,
ResolutionStrategy: tt.resolutionStrategy,
}
result, err := miseProvider.InstallTool(request)
require.NoError(t, err)
require.Equal(t, provider.ToolID("nixpkgs:ruby"), result.ToolName)
require.Equal(t, tt.expectedVersion, result.ConcreteVersion)
require.False(t, result.IsAlreadyInstalled)
})
}
}
2 changes: 1 addition & 1 deletion toolprovider/asdf/install_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (a *AsdfToolProvider) InstallPlugin(tool provider.ToolRequest) error {
log.Warnf("Failed to check if plugin is already installed: %v", err)
}
if installed {
log.Debugf("Tool plugin %s is already installed, skipping installation.", tool.ToolName)
log.Debugf("[TOOLPROVIDER] Tool plugin %s is already installed, skipping installation.", tool.ToolName)
return nil
}

Expand Down
25 changes: 20 additions & 5 deletions toolprovider/mise/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import (
)

func (m *MiseToolProvider) installToolVersion(tool provider.ToolRequest) error {
versionString, err := miseVersionString(tool, m.resolveToLatestInstalled)
backend := ""
if useNixPkgs(tool) {
backend = nixpkgsPluginLinkName
}

versionString, err := miseVersionString(tool, m.resolveToLatestInstalled, backend)
if err != nil {
return err
}
Expand All @@ -29,10 +34,14 @@ func (m *MiseToolProvider) installToolVersion(tool provider.ToolRequest) error {
// Helper for easier testing.
// Inputs: tool ID, tool version
// Returns: latest installed version of the tool, or an error if no matching version is installed
type latestInstalledResolver func(provider.ToolID, string) (string, error)
type latestInstalledResolver func(string, string) (string, error)

func isAlreadyInstalled(tool provider.ToolRequest, latestInstalledResolver latestInstalledResolver) (bool, error) {
_, err := latestInstalledResolver(tool.ToolName, tool.UnparsedVersion)
toolName := string(tool.ToolName)
if useNixPkgs(tool) {
toolName = nixpkgsPluginLinkName + ":" + toolName
}
_, err := latestInstalledResolver(toolName, tool.UnparsedVersion)
var isAlreadyInstalled bool
if err != nil {
if errors.Is(err, errNoMatchingVersion) {
Expand All @@ -46,7 +55,7 @@ func isAlreadyInstalled(tool provider.ToolRequest, latestInstalledResolver lates
return isAlreadyInstalled, nil
}

func miseVersionString(tool provider.ToolRequest, latestInstalledResolver latestInstalledResolver) (string, error) {
func miseVersionString(tool provider.ToolRequest, latestInstalledResolver latestInstalledResolver, backend string) (string, error) {
var miseVersionString string
resolutionStrategy := tool.ResolutionStrategy
if tool.UnparsedVersion == "installed" {
Expand All @@ -60,7 +69,7 @@ func miseVersionString(tool provider.ToolRequest, latestInstalledResolver latest
// https://mise.jdx.dev/configuration.html#scopes
miseVersionString = fmt.Sprintf("%s@prefix:%s", tool.ToolName, tool.UnparsedVersion)
case provider.ResolutionStrategyLatestInstalled:
latestInstalledV, err := latestInstalledResolver(tool.ToolName, tool.UnparsedVersion)
latestInstalledV, err := latestInstalledResolver(string(tool.ToolName), tool.UnparsedVersion)
if err == nil {
miseVersionString = fmt.Sprintf("%s@%s", tool.ToolName, latestInstalledV)
} else {
Expand All @@ -74,6 +83,12 @@ func miseVersionString(tool provider.ToolRequest, latestInstalledResolver latest
default:
return "", fmt.Errorf("unknown resolution strategy: %v", tool.ResolutionStrategy)
}

if backend != "" {
// https://mise.jdx.dev/configuration.html#backends
miseVersionString = fmt.Sprintf("%s:%s", backend, miseVersionString)
}

return miseVersionString, nil

}
4 changes: 2 additions & 2 deletions toolprovider/mise/install_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (m *MiseToolProvider) InstallPlugin(tool provider.ToolRequest) error {
}
if plugin == nil {
// No plugin installation needed (either core tool or registry tool).
log.Debugf("No plugin installation needed for tool %s", tool.ToolName)
log.Debugf("[TOOLPROVIDER] No plugin installation needed for tool %s", tool.ToolName)
return nil
}

Expand All @@ -53,7 +53,7 @@ func (m *MiseToolProvider) InstallPlugin(tool provider.ToolRequest) error {
log.Warnf("Failed to check if plugin is already installed: %v", err)
}
if installed {
log.Debugf("Tool plugin %s is already installed, skipping installation.", tool.ToolName)
log.Debugf("[TOOLPROVIDER] Tool plugin %s is already installed, skipping installation.", tool.ToolName)
return nil
}

Expand Down
35 changes: 32 additions & 3 deletions toolprovider/mise/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func TestMiseVersionString(t *testing.T) {
tests := []struct {
name string
tool provider.ToolRequest
backend string
want string
wantErr bool
}{
Expand All @@ -23,6 +24,7 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "18.20.0",
ResolutionStrategy: provider.ResolutionStrategyStrict,
},
backend: "",
want: "[email protected]",
wantErr: false,
},
Expand All @@ -33,6 +35,7 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "3.11",
ResolutionStrategy: provider.ResolutionStrategyLatestReleased,
},
backend: "",
want: "python@prefix:3.11",
wantErr: false,
},
Expand All @@ -43,6 +46,7 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "1.21",
ResolutionStrategy: provider.ResolutionStrategyLatestInstalled,
},
backend: "",
want: "[email protected]",
wantErr: false,
},
Expand All @@ -53,6 +57,7 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "17",
ResolutionStrategy: provider.ResolutionStrategyLatestInstalled,
},
backend: "",
want: "java@prefix:17",
wantErr: false,
},
Expand All @@ -63,6 +68,7 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "3.0",
ResolutionStrategy: provider.ResolutionStrategyLatestInstalled,
},
backend: "",
want: "",
wantErr: true,
},
Expand All @@ -73,14 +79,37 @@ func TestMiseVersionString(t *testing.T) {
UnparsedVersion: "18.0.0",
ResolutionStrategy: provider.ResolutionStrategy(999),
},
backend: "",
want: "",
wantErr: true,
},
{
name: "strict resolution with nixpkgs backend",
tool: provider.ToolRequest{
ToolName: "ruby",
UnparsedVersion: "3.3.0",
ResolutionStrategy: provider.ResolutionStrategyStrict,
},
backend: "nixpkgs",
want: "nixpkgs:[email protected]",
wantErr: false,
},
{
name: "latest released with nixpkgs backend",
tool: provider.ToolRequest{
ToolName: "ruby",
UnparsedVersion: "3.3",
ResolutionStrategy: provider.ResolutionStrategyLatestReleased,
},
backend: "nixpkgs",
want: "nixpkgs:ruby@prefix:3.3",
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
latestInstalledResolver := func(toolName provider.ToolID, version string) (string, error) {
latestInstalledResolver := func(toolName, version string) (string, error) {
// Setup fake behavior based on test case
switch tt.tool.ToolName {
case "go":
Expand All @@ -96,7 +125,7 @@ func TestMiseVersionString(t *testing.T) {
return "", fmt.Errorf("no fake behavior defined for tool %s", toolName)
}

got, err := miseVersionString(tt.tool, latestInstalledResolver)
got, err := miseVersionString(tt.tool, latestInstalledResolver, tt.backend)

if tt.wantErr {
require.Error(t, err)
Expand Down Expand Up @@ -151,7 +180,7 @@ func TestIsAlreadyInstalled(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
latestInstalledResolver := func(toolName provider.ToolID, version string) (string, error) {
latestInstalledResolver := func(toolName, version string) (string, error) {
if tt.latestInstalledError != nil {
return "", tt.latestInstalledError
}
Expand Down
Loading
Loading