Skip to content

Commit 4b6c07d

Browse files
authored
Toolprovider: Mise (#1115)
* Toolprovider: Mise * Mise: check if version exists before install * Instantiate Mise provider * Upgrade Mise * Fix detection of installed version when Mise logs other messages * Add more integration tests for supported tools * Add integration test for Mise config validation
1 parent 6a12eb2 commit 4b6c07d

22 files changed

+1151
-9
lines changed

_tests/integration/toolprovider/asdf/install_error_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestNoMatchingVersionError(t *testing.T) {
3232

3333
var installErr provider.ToolInstallError
3434
require.ErrorAs(t, err, &installErr)
35-
require.Equal(t, "nodejs", installErr.ToolName)
35+
require.Equal(t, provider.ToolID("nodejs"), installErr.ToolName)
3636
require.Equal(t, "22", installErr.RequestedVersion)
3737
require.Contains(t, installErr.Error(), "no match for requested version 22")
3838
require.Contains(t, installErr.Recommendation, "22:latest")
@@ -60,7 +60,7 @@ func TestNewToolPluginError(t *testing.T) {
6060

6161
var installErr provider.ToolInstallError
6262
require.ErrorAs(t, err, &installErr)
63-
require.Equal(t, "foo", installErr.ToolName)
63+
require.Equal(t, provider.ToolID("foo"), installErr.ToolName)
6464
require.Equal(t, "1.0.0", installErr.RequestedVersion)
6565
require.Equal(t, installErr.Cause, "This tool integration (foo) is not tested or vetted by Bitrise.")
6666
require.Equal(t, installErr.Recommendation, "If you want to use this tool anyway, look up its asdf plugin and provide it in the `plugin` field of the tool declaration. For example: `plugin: foo::https://github/url/to/asdf/plugin/repo.git`")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//go:build linux_and_mac
2+
// +build linux_and_mac
3+
4+
package mise
5+
6+
import (
7+
"testing"
8+
9+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
10+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestNoMatchingVersionError(t *testing.T) {
15+
miseInstallDir := t.TempDir()
16+
miseDataDir := t.TempDir()
17+
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
18+
require.NoError(t, err)
19+
20+
err = miseProvider.Bootstrap()
21+
require.NoError(t, err)
22+
23+
request := provider.ToolRequest{
24+
ToolName: provider.ToolID("nodejs"),
25+
UnparsedVersion: "0.1.0",
26+
ResolutionStrategy: provider.ResolutionStrategyStrict,
27+
}
28+
_, err = miseProvider.InstallTool(request)
29+
require.Error(t, err)
30+
31+
var installErr provider.ToolInstallError
32+
require.ErrorAs(t, err, &installErr)
33+
require.Equal(t, provider.ToolID("nodejs"), installErr.ToolName)
34+
require.Equal(t, "0.1.0", installErr.RequestedVersion)
35+
require.Contains(t, installErr.Error(), "failed to install nodejs 0.1.0")
36+
require.Contains(t, installErr.Cause, "no match for requested version 0.1.0")
37+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//go:build linux_and_mac
2+
// +build linux_and_mac
3+
4+
package mise
5+
6+
import (
7+
"testing"
8+
9+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
10+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestAsdfInstallFlutter(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
requestedVersion string
18+
resolutionStrategy provider.ResolutionStrategy
19+
expectedVersion string
20+
}{
21+
{"Install specific version", "3.32.1-stable", provider.ResolutionStrategyStrict, "3.32.1-stable"},
22+
}
23+
24+
for _, tt := range tests {
25+
miseInstallDir := t.TempDir()
26+
miseDataDir := t.TempDir()
27+
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
28+
require.NoError(t, err)
29+
30+
err = miseProvider.Bootstrap()
31+
require.NoError(t, err)
32+
33+
t.Run(tt.name, func(t *testing.T) {
34+
request := provider.ToolRequest{
35+
ToolName: "flutter",
36+
UnparsedVersion: tt.requestedVersion,
37+
ResolutionStrategy: tt.resolutionStrategy,
38+
}
39+
result, err := miseProvider.InstallTool(request)
40+
require.NoError(t, err)
41+
require.Equal(t, provider.ToolID("flutter"), result.ToolName)
42+
require.Equal(t, tt.expectedVersion, result.ConcreteVersion)
43+
require.False(t, result.IsAlreadyInstalled)
44+
})
45+
}
46+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//go:build linux_and_mac
2+
// +build linux_and_mac
3+
4+
package mise
5+
6+
import (
7+
"testing"
8+
9+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
10+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestAsdfInstallGolangVersion(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
requestedVersion string
18+
resolutionStrategy provider.ResolutionStrategy
19+
expectedVersion string
20+
}{
21+
{"Install specific version", "1.23.4", provider.ResolutionStrategyStrict, "1.23.4"},
22+
{"Install partial major.minor version", "1.22", provider.ResolutionStrategyLatestInstalled, "1.22.12"},
23+
{"Install partial major.minor version, latest released", "1.22", provider.ResolutionStrategyLatestReleased, "1.22.12"},
24+
}
25+
26+
for _, tt := range tests {
27+
miseInstallDir := t.TempDir()
28+
miseDataDir := t.TempDir()
29+
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
30+
require.NoError(t, err)
31+
32+
err = miseProvider.Bootstrap()
33+
require.NoError(t, err)
34+
35+
t.Run(tt.name, func(t *testing.T) {
36+
request := provider.ToolRequest{
37+
ToolName: "golang",
38+
UnparsedVersion: tt.requestedVersion,
39+
ResolutionStrategy: tt.resolutionStrategy,
40+
}
41+
result, err := miseProvider.InstallTool(request)
42+
require.NoError(t, err)
43+
require.Equal(t, provider.ToolID("golang"), result.ToolName)
44+
require.Equal(t, tt.expectedVersion, result.ConcreteVersion)
45+
require.False(t, result.IsAlreadyInstalled)
46+
})
47+
}
48+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package mise
2+
3+
import (
4+
"testing"
5+
6+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
7+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestMiseInstallJavaVersion(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
requestedVersion string
15+
resolutionStrategy provider.ResolutionStrategy
16+
expectedVersion string
17+
}{
18+
{
19+
name: "OpenJDK major version only",
20+
requestedVersion: "21",
21+
resolutionStrategy: provider.ResolutionStrategyStrict,
22+
expectedVersion: "21.0.2",
23+
},
24+
{
25+
name: "OpenJDK major version only, latest released",
26+
requestedVersion: "17",
27+
resolutionStrategy: provider.ResolutionStrategyLatestReleased,
28+
expectedVersion: "17.0.2",
29+
},
30+
{
31+
name: "Temurin major version only",
32+
requestedVersion: "temurin-22",
33+
resolutionStrategy: provider.ResolutionStrategyLatestReleased,
34+
expectedVersion: "temurin-22.0.2+9",
35+
},
36+
{
37+
name: "Temurin exact version",
38+
requestedVersion: "temurin-18.0.2+9",
39+
resolutionStrategy: provider.ResolutionStrategyStrict,
40+
expectedVersion: "temurin-18.0.2+9",
41+
},
42+
}
43+
44+
for _, tt := range tests {
45+
miseInstallDir := t.TempDir()
46+
miseDataDir := t.TempDir()
47+
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
48+
require.NoError(t, err)
49+
50+
err = miseProvider.Bootstrap()
51+
require.NoError(t, err)
52+
53+
t.Run(tt.name, func(t *testing.T) {
54+
request := provider.ToolRequest{
55+
ToolName: provider.ToolID("java"),
56+
UnparsedVersion: tt.requestedVersion,
57+
ResolutionStrategy: tt.resolutionStrategy,
58+
}
59+
result, err := miseProvider.InstallTool(request)
60+
require.NoError(t, err)
61+
require.Equal(t, provider.ToolID("java"), result.ToolName)
62+
require.Equal(t, tt.expectedVersion, result.ConcreteVersion)
63+
require.False(t, result.IsAlreadyInstalled)
64+
})
65+
}
66+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package mise
2+
3+
import (
4+
"testing"
5+
6+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
7+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestMiseInstallNodeVersion(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
requestedVersion string
15+
resolutionStrategy provider.ResolutionStrategy
16+
expectedVersion string
17+
}{
18+
{"Install specific version", "18.16.0", provider.ResolutionStrategyStrict, "18.16.0"},
19+
{"Install partial major version", "18", provider.ResolutionStrategyLatestInstalled, "18.20.8"},
20+
{"Install partial major.minor version", "18.10", provider.ResolutionStrategyLatestReleased, "18.10.0"},
21+
}
22+
23+
for _, tt := range tests {
24+
miseInstallDir := t.TempDir()
25+
miseDataDir := t.TempDir()
26+
miseProvider, err := mise.NewToolProvider(miseInstallDir, miseDataDir)
27+
require.NoError(t, err)
28+
29+
err = miseProvider.Bootstrap()
30+
require.NoError(t, err)
31+
32+
t.Run(tt.name, func(t *testing.T) {
33+
request := provider.ToolRequest{
34+
ToolName: provider.ToolID("nodejs"),
35+
UnparsedVersion: tt.requestedVersion,
36+
ResolutionStrategy: tt.resolutionStrategy,
37+
}
38+
result, err := miseProvider.InstallTool(request)
39+
require.NoError(t, err)
40+
require.Equal(t, provider.ToolID("nodejs"), result.ToolName)
41+
require.Equal(t, tt.expectedVersion, result.ConcreteVersion)
42+
require.False(t, result.IsAlreadyInstalled)
43+
})
44+
}
45+
}

_tests/integration/toolprovider_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,14 @@ import (
1010
"github.com/stretchr/testify/require"
1111
)
1212

13-
func TestToolProvider(t *testing.T) {
13+
func TestDefaultToolProvider(t *testing.T) {
1414
cmd := command.New(binPath(), "run", "toolprovider_test", "--config", "toolprovider_test_bitrise.yml")
1515
out, err := cmd.RunAndReturnTrimmedCombinedOutput()
1616
require.NoError(t, err, out)
1717
}
18+
19+
func TestMiseToolProvider(t *testing.T) {
20+
cmd := command.New(binPath(), "run", "toolprovider_test", "--config", "toolprovider_test_mise_bitrise.yml")
21+
out, err := cmd.RunAndReturnTrimmedCombinedOutput()
22+
require.NoError(t, err, out)
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
format_version: "17"
2+
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
3+
4+
tools:
5+
nodejs: 22:latest
6+
tool_config:
7+
provider: mise
8+
9+
workflows:
10+
toolprovider_test:
11+
steps:
12+
- script@1:
13+
title: Test activated tool
14+
inputs:
15+
- content: set -ex; node --version | grep -q "22"

_tests/integration/validate_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,27 @@ tool_config:
7575
extra_plugins:
7676
empty-url-tool: ""
7777
`
78+
const miseToolConfigYML = `format_version: 11
79+
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
80+
81+
tools:
82+
golang: "1.20.3"
83+
nodejs: "20:latest"
84+
ruby: "3.2:installed"
85+
86+
tool_config:
87+
provider: mise
88+
extra_plugins:
89+
flutter: "https://github.com/asdf-community/asdf-flutter.git"
90+
custom-tool: "https://github.com/user/asdf-custom-tool.git"
91+
92+
workflows:
93+
test:
94+
steps:
95+
- script:
96+
inputs:
97+
- content: echo "hello"
98+
`
7899
const runtimeLimit = 1000 * time.Millisecond
79100
const runningTimeMsg = "test case too slow: %s is %s above limit"
80101

@@ -272,6 +293,22 @@ func Test_InvalidToolConfigValidateTest(t *testing.T) {
272293
require.Equal(t, true, elapsed < runtimeLimit, runningTimeMsg, elapsed, elapsed-runtimeLimit)
273294
}
274295

296+
func Test_ValidMiseToolConfigValidateTest(t *testing.T) {
297+
tmpDir := t.TempDir()
298+
configPth := filepath.Join(tmpDir, "bitrise.yml")
299+
require.NoError(t, fileutil.WriteStringToFile(configPth, miseToolConfigYML))
300+
301+
var out string
302+
var err error
303+
elapsed := withRunningTimeCheck(func() {
304+
cmd := command.New(binPath(), "validate", "-c", configPth)
305+
out, err = cmd.RunAndReturnTrimmedCombinedOutput()
306+
})
307+
require.NoError(t, err, out)
308+
require.Equal(t, "Config is valid: \x1b[32;1mtrue\x1b[0m", out)
309+
require.Equal(t, true, elapsed < runtimeLimit, runningTimeMsg, elapsed, elapsed-runtimeLimit)
310+
}
311+
275312
func Test_SecretValidateTest(t *testing.T) {
276313
tmpDir, err := pathutil.NormalizedOSTempDirPath("__validate_test__")
277314
require.NoError(t, err)

toolprovider/asdf/asdf.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (a AsdfToolProvider) InstallTool(tool provider.ToolRequest) (provider.ToolI
8181
if err != nil {
8282
if errors.As(err, &nomatchErr) {
8383
errorDetails := provider.ToolInstallError{
84-
ToolName: string(tool.ToolName),
84+
ToolName: tool.ToolName,
8585
RequestedVersion: tool.UnparsedVersion,
8686
Cause: nomatchErr.Error(),
8787
Recommendation: fmt.Sprintf("You might want to use `%s:installed` or `%s:latest` to install the latest installed or latest released version of %s %s.", tool.UnparsedVersion, tool.UnparsedVersion, tool.ToolName, tool.UnparsedVersion),

0 commit comments

Comments
 (0)