Skip to content

Commit 661ecec

Browse files
committed
SImplify things
1 parent c177efe commit 661ecec

File tree

4 files changed

+81
-127
lines changed

4 files changed

+81
-127
lines changed

toolprovider/mise/install_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func TestMiseVersionString(t *testing.T) {
8686
want: "nixpkgs:[email protected]",
8787
wantErr: false,
8888
},
89+
// TODO: more test cases?
8990
}
9091

9192
for _, tt := range tests {

toolprovider/mise/mise.go

Lines changed: 45 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import (
44
"errors"
55
"fmt"
66
"os"
7-
"os/exec"
87
"path/filepath"
98
"strings"
109

1110
"github.com/bitrise-io/bitrise/v2/log"
1211
"github.com/bitrise-io/bitrise/v2/toolprovider/mise/execenv"
12+
"github.com/bitrise-io/bitrise/v2/toolprovider/mise/nixpkgs"
1313
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
1414
)
1515

@@ -41,11 +41,6 @@ var miseStableChecksums = map[string]string{
4141
"macos-arm64": "0b5893de7c8c274736867b7c4c7ed565b4429f4d6272521ace802f8a21422319",
4242
}
4343

44-
const (
45-
nixpkgsPluginGitURL = "https://github.com/bitrise-io/mise-nixpkgs-plugin.git"
46-
nixpkgsPluginName = "mise-nixpkgs-plugin"
47-
)
48-
4944
type MiseToolProvider struct {
5045
ExecEnv execenv.ExecEnv
5146
}
@@ -108,49 +103,60 @@ func (m *MiseToolProvider) Bootstrap() error {
108103
}
109104

110105
func (m *MiseToolProvider) InstallTool(tool provider.ToolRequest) (provider.ToolInstallResult, error) {
111-
useNix := m.shouldUseNixPkgs(tool)
106+
useNix, err := m.ShouldInstallWithNix(tool)
107+
if err != nil {
108+
return provider.ToolInstallResult{}, err
109+
}
112110

113-
if useNix {
114-
tool.ToolName = provider.ToolID(fmt.Sprintf("nixpkgs:%s", tool.ToolName))
115-
} else {
116-
err := m.InstallPlugin(tool)
111+
if !useNix {
112+
err = m.InstallPlugin(tool)
117113
if err != nil {
118114
return provider.ToolInstallResult{}, fmt.Errorf("install tool plugin %s: %w", tool.ToolName, err)
119115
}
120116
}
121117

122-
isAlreadyInstalled, err := isAlreadyInstalled(tool, m.resolveToLatestInstalled)
118+
var installRequest provider.ToolRequest
119+
if useNix {
120+
installRequest = provider.ToolRequest{
121+
// Use Mise's backend plugin convention of pluginID:toolID
122+
ToolName: provider.ToolID(fmt.Sprintf("nixpkgs:%s", tool.ToolName)),
123+
UnparsedVersion: tool.UnparsedVersion,
124+
ResolutionStrategy: tool.ResolutionStrategy,
125+
PluginURL: nil, // Not relevant when using nixpkgs backend plugin
126+
}
127+
} else {
128+
installRequest = tool
129+
}
130+
131+
isAlreadyInstalled, err := isAlreadyInstalled(installRequest, m.resolveToLatestInstalled)
123132
if err != nil {
124133
return provider.ToolInstallResult{}, err
125134
}
126135

127-
if !useNix {
128-
// Nix already checks version existence previously
129-
versionExists, err := m.versionExists(tool.ToolName, tool.UnparsedVersion)
130-
if err != nil {
131-
return provider.ToolInstallResult{}, fmt.Errorf("check if version exists: %w", err)
132-
}
133-
if !versionExists {
134-
return provider.ToolInstallResult{}, provider.ToolInstallError{
135-
ToolName: tool.ToolName,
136-
RequestedVersion: tool.UnparsedVersion,
137-
Cause: fmt.Sprintf("no match for requested version %s", tool.UnparsedVersion),
138-
}
136+
versionExists, err := m.versionExists(tool.ToolName, tool.UnparsedVersion)
137+
if err != nil {
138+
return provider.ToolInstallResult{}, fmt.Errorf("check if version exists: %w", err)
139+
}
140+
if !versionExists {
141+
return provider.ToolInstallResult{}, provider.ToolInstallError{
142+
ToolName: tool.ToolName,
143+
RequestedVersion: tool.UnparsedVersion,
144+
Cause: fmt.Sprintf("no match for requested version %s", tool.UnparsedVersion),
139145
}
140146
}
141147

142-
err = m.installToolVersion(tool)
148+
err = m.installToolVersion(installRequest)
143149
if err != nil {
144150
return provider.ToolInstallResult{}, err
145151
}
146152

147-
concreteVersion, err := m.resolveToConcreteVersionAfterInstall(tool)
153+
concreteVersion, err := m.resolveToConcreteVersionAfterInstall(installRequest)
148154
if err != nil {
149155
return provider.ToolInstallResult{}, fmt.Errorf("resolve exact version after install: %w", err)
150156
}
151157

152158
return provider.ToolInstallResult{
153-
ToolName: tool.ToolName,
159+
ToolName: installRequest.ToolName,
154160
IsAlreadyInstalled: isAlreadyInstalled,
155161
ConcreteVersion: concreteVersion,
156162
}, nil
@@ -195,111 +201,27 @@ func GetMiseChecksums() map[string]string {
195201
return miseStableChecksums
196202
}
197203

198-
func useNixPkgs(tool provider.ToolRequest) bool {
199-
// Note: Add other tools here if needed
200-
if tool.ToolName != "ruby" {
201-
log.Debugf("[TOOLPROVIDER] Nix packages are only supported for ruby tool, current tool: %s", tool.ToolName)
202-
return false
203-
}
204-
205-
if value, variablePresent := os.LookupEnv("BITRISEIO_MISE_LEGACY_INSTALL"); variablePresent && strings.Contains(value, "1") {
206-
log.Debugf("[TOOLPROVIDER] Using legacy install (non-nix) for tool: %s", tool.ToolName)
207-
return false
204+
func (m *MiseToolProvider) ShouldInstallWithNix(tool provider.ToolRequest) (bool, error) {
205+
if !nixpkgs.ShouldUseBackend(tool) {
206+
return false, nil
208207
}
209208

210-
return true
211-
}
212-
213-
// shouldUseNixPkgs checks if Nix packages should be used for the tool installation.
214-
// It validates that the tool is eligible for Nix, the plugin is available, and the version exists in the index.
215-
// Returns false and logs a warning if any validation fails, falling back to legacy installation.
216-
func (m *MiseToolProvider) shouldUseNixPkgs(tool provider.ToolRequest) bool {
217-
if !useNixPkgs(tool) {
218-
return false
219-
}
220-
221-
if err := m.getNixpkgsPlugin(); err != nil {
222-
log.Warnf("Failed to link nixpkgs plugin: %v. Falling back to legacy installation.", err)
223-
return false
209+
output, err := m.ExecEnv.RunMisePlugin("install", nixpkgs.PluginName, nixpkgs.PluginGitURL)
210+
if err != nil {
211+
return false, fmt.Errorf("install %s: %s", nixpkgs.PluginGitURL, output)
224212
}
225213

226214
nameWithBackend := provider.ToolID(fmt.Sprintf("nixpkgs:%s", tool.ToolName))
227215

228216
available, err := m.versionExists(nameWithBackend, tool.UnparsedVersion)
229-
if err != nil || !available {
230-
log.Warnf("Failed to check nixpkgs index for %s@%s: %v. Falling back to legacy installation.", tool.ToolName, tool.UnparsedVersion, err)
231-
return false
232-
}
233-
234-
return true
235-
}
236-
237-
// findPluginPath finds the nixpkgs plugin directory relative to the bitrise executable.
238-
// It first checks next to the binary, then tries a dev location one directory up.
239-
// Returns the path if found, otherwise returns an error.
240-
func findPluginPath() (string, error) {
241-
execPath, err := os.Executable()
242-
if err != nil {
243-
return "", fmt.Errorf("get executable path: %w", err)
244-
}
245-
246-
execDir := filepath.Dir(execPath)
247-
pluginPath := filepath.Join(execDir, nixpkgsPluginName)
248-
249-
// Check if the plugin exists besides the binary
250-
if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
251-
// Try dev location
252-
pluginPath = filepath.Join(execDir, "..", nixpkgsPluginName)
253-
if _, err := os.Stat(pluginPath); os.IsNotExist(err) {
254-
return "", fmt.Errorf("%s not found", nixpkgsPluginName)
255-
}
256-
}
257-
258-
return pluginPath, nil
259-
}
260-
261-
// getNixpkgsPlugin clones or updates the nixpkgs backend plugin and links it to mise.
262-
// If the plugin directory doesn't exist, it clones from the git URL.
263-
// If it exists, it checks out the specified commit/branch.
264-
func (m *MiseToolProvider) getNixpkgsPlugin() error {
265-
pluginPath, err := findPluginPath()
266-
needsClone := false
267-
if err != nil {
268-
// Plugin doesn't exist, we need to clone it
269-
needsClone = true
270-
execPath, execErr := os.Executable()
271-
if execErr != nil {
272-
return fmt.Errorf("get executable path: %w", execErr)
273-
}
274-
pluginPath = filepath.Join(filepath.Dir(execPath), nixpkgsPluginName)
275-
}
276-
277-
if needsClone {
278-
if err := cloneGitRepo(nixpkgsPluginGitURL, pluginPath); err != nil {
279-
return fmt.Errorf("clone nixpkgs plugin: %w", err)
280-
}
281-
}
282-
283-
// Link the plugin using mise plugin link
284-
_, err = m.ExecEnv.RunMisePlugin("link", "--force", "nixpkgs", pluginPath)
285217
if err != nil {
286-
return fmt.Errorf("link nixpkgs plugin: %w", err)
218+
log.Warnf("Error while checking nixpkgs index for %s@%s: %v. Falling back to core plugin installation.", tool.ToolName, tool.UnparsedVersion, err)
219+
return false, nil
287220
}
288-
289-
// Enable experimental settings for custom backend
290-
if _, err := m.ExecEnv.RunMise("settings", "experimental=true"); err != nil {
291-
return fmt.Errorf("enable experimental settings: %w", err)
221+
if !available {
222+
log.Warnf("%s@%s not found in nixpkgs index, doing a source build. This may take some time...", tool.ToolName, tool.UnparsedVersion)
223+
return false, nil
292224
}
293225

294-
return nil
295-
}
296-
297-
// cloneGitRepo clones a git repository to the specified path with minimal history.
298-
func cloneGitRepo(repoURL, destPath string) error {
299-
cmd := exec.Command("git", "clone", "--depth", "1", "--no-tags", repoURL, destPath)
300-
output, err := cmd.CombinedOutput()
301-
if err != nil {
302-
return fmt.Errorf("git clone failed: %w: %s", err, string(output))
303-
}
304-
return nil
226+
return true, nil
305227
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package nixpkgs
2+
3+
import (
4+
"os"
5+
"strings"
6+
7+
"github.com/bitrise-io/bitrise/v2/log"
8+
"github.com/bitrise-io/bitrise/v2/toolprovider/provider"
9+
)
10+
11+
const (
12+
PluginGitURL = "https://github.com/bitrise-io/mise-nixpkgs-plugin.git"
13+
PluginName = "mise-nixpkgs-plugin"
14+
)
15+
16+
// TODO: check if Nix works at all
17+
18+
func ShouldUseBackend(request provider.ToolRequest) bool {
19+
if request.ToolName != "ruby" {
20+
log.Debugf("[TOOLPROVIDER] The mise-nixpkgs backend is only enabled for Ruby for now. Using core plugin to install %s", request.ToolName)
21+
return false
22+
}
23+
24+
value, ok := os.LookupEnv("BITRISE_TOOLSETUP_FAST_INSTALL")
25+
if ok && strings.TrimSpace(value) == "1" {
26+
log.Debugf("[TOOLPROVIDER] Using nixpkgs backend for %s as BITRISE_TOOLSETUP_FAST_INSTALL is set", request.ToolName)
27+
return true
28+
}
29+
log.Debugf("[TOOLPROVIDER] Using core plugin for %s", request.ToolName)
30+
return false
31+
}

toolprovider/mise/resolve.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,19 @@ func versionExists(executor MiseExecutor, toolName provider.ToolID, version stri
103103
// Fallback: no installed versions found, fall through to remote (ls-remote) existence check.
104104
}
105105

106-
search := string(toolName)
106+
versionString := string(toolName)
107107
if version != "" && version != "latest" && version != "installed" {
108-
search = fmt.Sprintf("%s@%s", toolName, version)
108+
versionString = fmt.Sprintf("%s@%s", toolName, version)
109109
}
110110

111111
// Notes:
112112
// - ls-remote accepts both fuzzy and concrete versions
113113
// - it can return multiple versions (one per line) when a fuzzy version is provided
114114
// - in case of no matching version, the exit code is still 0, just there is no output
115115
// - in case of a non-existing tool, the exit code is 1, but a non-existing tool ID fails earlier than this check
116-
output, err := executor.RunMiseWithTimeout(execenv.DefaultTimeout, "ls-remote", "--quiet", search)
116+
output, err := executor.RunMiseWithTimeout(execenv.DefaultTimeout, "ls-remote", "--quiet", versionString)
117117
if err != nil {
118-
return false, fmt.Errorf("mise ls-remote %s: %w", search, err)
118+
return false, fmt.Errorf("mise ls-remote %s: %w", versionString, err)
119119
}
120120

121121
return strings.TrimSpace(string(output)) != "", nil

0 commit comments

Comments
 (0)