Skip to content

Commit a71a2d5

Browse files
authored
[CRE-782] allow passing env vars to loopinstall's install command (#1683)
* allow passing env vars to loopinstall's install command * switch go install for go build and always pass existing env vars while replacing them with custom ones * update help * add tests for custom env vars * unified handling of replacing vs appending of env vars with correct precedence
1 parent 70bb73d commit a71a2d5

File tree

4 files changed

+442
-37
lines changed

4 files changed

+442
-37
lines changed

pkg/loop/cmd/loopinstall/install.go

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,38 @@ var execCommand = func(cmd *exec.Cmd) error {
1919
return cmd.Run()
2020
}
2121

22+
// mergeOrReplaceEnvVars merges new environment variables into an existing slice,
23+
// replacing any existing variables with the same key
24+
func mergeOrReplaceEnvVars(existing []string, newVars []string) []string {
25+
result := make([]string, len(existing))
26+
copy(result, existing)
27+
28+
for _, newVar := range newVars {
29+
parts := strings.SplitN(newVar, "=", 2)
30+
if len(parts) != 2 {
31+
continue
32+
}
33+
key := parts[0]
34+
35+
// Find and replace if it exists
36+
found := false
37+
for i, existingVar := range result {
38+
if strings.HasPrefix(existingVar, key+"=") {
39+
result[i] = newVar
40+
found = true
41+
break
42+
}
43+
}
44+
45+
// Append if not found
46+
if !found {
47+
result = append(result, newVar)
48+
}
49+
}
50+
51+
return result
52+
}
53+
2254
// downloadAndInstallPlugin downloads and installs a single plugin
2355
func downloadAndInstallPlugin(pluginType string, pluginIdx int, plugin PluginDef, defaults DefaultsConfig) error {
2456
if !isPluginEnabled(plugin) {
@@ -123,6 +155,17 @@ func downloadAndInstallPlugin(pluginType string, pluginIdx int, plugin PluginDef
123155
}
124156
}
125157

158+
// Build env vars from defaults, environment variable, and plugin-specific settings
159+
envVars := defaults.EnvVars
160+
if envEnvVars := os.Getenv("CL_PLUGIN_ENVVARS"); envEnvVars != "" {
161+
envVars = mergeOrReplaceEnvVars(envVars, strings.Fields(envEnvVars))
162+
}
163+
164+
// Merge plugin-specific env vars
165+
if len(plugin.EnvVars) != 0 {
166+
envVars = mergeOrReplaceEnvVars(envVars, plugin.EnvVars)
167+
}
168+
126169
// Install the plugin
127170
{
128171
// Determine the actual argument for 'go install' based on installPath and moduleURI.
@@ -162,41 +205,45 @@ func downloadAndInstallPlugin(pluginType string, pluginIdx int, plugin PluginDef
162205
}
163206
}
164207

165-
args := []string{"install"}
208+
binaryName := filepath.Base(installArg)
209+
if binaryName == "." {
210+
binaryName = filepath.Base(moduleURI)
211+
}
212+
213+
// Determine output directory
214+
outputDir := os.Getenv("GOBIN")
215+
if outputDir == "" {
216+
gopath := os.Getenv("GOPATH")
217+
if gopath == "" {
218+
gopath = filepath.Join(os.Getenv("HOME"), "go")
219+
}
220+
outputDir = filepath.Join(gopath, "bin")
221+
}
222+
223+
outputPath := filepath.Join(outputDir, binaryName)
224+
225+
args := []string{"build", "-o", outputPath}
166226
if goflags != "" {
167227
args = append(args, strings.Fields(goflags)...)
168228
}
169-
// Add the install path, which is now relative to the module root or ".".
170229
args = append(args, installArg)
171230

172231
cmd := exec.Command("go", args...)
173232
cmd.Dir = moduleDir
174233
cmd.Stdout = os.Stdout
175234
cmd.Stderr = os.Stderr
176235

177-
// Set GOPRIVATE environment variable while preserving other environment variables
178-
if goPrivate != "" {
179-
// Start with all current environment variables
180-
env := os.Environ()
181-
182-
// Find and replace GOPRIVATE if it exists, or add it if it doesn't
183-
goprivateFound := false
184-
for i, e := range env {
185-
if strings.HasPrefix(e, "GOPRIVATE=") {
186-
env[i] = "GOPRIVATE=" + goPrivate
187-
goprivateFound = true
188-
break
189-
}
190-
}
191-
192-
// Add GOPRIVATE if it wasn't already in the environment
193-
if !goprivateFound {
194-
env = append(env, "GOPRIVATE="+goPrivate)
195-
}
236+
// Start with all current environment variables
237+
cmd.Env = os.Environ()
196238

197-
cmd.Env = env
239+
// Set GOPRIVATE environment variable if provided
240+
if goPrivate != "" {
241+
cmd.Env = mergeOrReplaceEnvVars(cmd.Env, []string{"GOPRIVATE=" + goPrivate})
198242
}
199243

244+
// Add/replace custom environment variables (e.g., GOOS, GOARCH, CGO_ENABLED)
245+
cmd.Env = mergeOrReplaceEnvVars(cmd.Env, envVars)
246+
200247
log.Printf("Running install command: go %s (in directory: %s)", strings.Join(args, " "), moduleDir)
201248

202249
if err := execCommand(cmd); err != nil {

pkg/loop/cmd/loopinstall/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,20 @@ Examples:
117117
# Install plugins sequentially
118118
loopinstall -s plugins.default.yaml
119119
120-
# Install plugins with environment variable overrides
120+
# Install plugins with go flags variable overrides
121121
CL_PLUGIN_GOFLAGS="-ldflags='-s'" loopinstall plugins.default.yaml
122122
123+
# Install plugins with custom environment variables
124+
CL_PLUGIN_ENVVARS="GOOS=linux GOARCH=amd64 CGO_ENABLED=0" loopinstall plugins.default.yaml
125+
123126
Environment Variables:
124127
CL_PLUGIN_GOFLAGS Override the goflags option from the configuration
128+
CL_PLUGIN_ENVVARS Space-separated list of environment variables to set during installation (for example for cross-compilation)
125129
126130
Plugin Configuration Format:
127131
defaults:
128132
goflags: "" # Default Go build flags
133+
envvars: [] # Default environment variables
129134
130135
plugins:
131136
plugin-type:

0 commit comments

Comments
 (0)