Skip to content

Commit c663ddc

Browse files
authored
[env] Add --env and --env-file flags (#1353)
## Summary Adds `--env` and `--env-file` flags that can be used with `run` `shell` and `services` If both flags are specified they are merged with `--env` taking precedence. environment variables passed in with flags take the highest level of precedence, replacing any env variables set by nix, devbox.json, or plugins. TODO: The flag code is a bit brittle and repetitive, I think we can consolidate the common flag registration. ## How was it tested? ``` devbox run -e FOO=BAR echo \$FOO devbox services up -e HTTPD_PORT=8083 ```
1 parent 1f177a0 commit c663ddc

File tree

10 files changed

+104
-1
lines changed

10 files changed

+104
-1
lines changed

examples/servers/apache/devbox.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
"packages": {
44
"apacheHttpd@latest": {
55
"last_modified": "2023-05-01T16:53:22Z",
6+
"plugin_version": "0.0.2",
67
"resolved": "github:NixOS/nixpkgs/8670e496ffd093b60e74e7fa53526aa5920d09eb#apacheHttpd",
78
"version": "2.4.57"
89
}
910
}
10-
}
11+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ require (
4545
gopkg.in/yaml.v3 v3.0.1
4646
)
4747

48+
require github.com/joho/godotenv v1.5.1
49+
4850
require (
4951
github.com/bahlo/generic-list-go v0.2.0 // indirect
5052
github.com/buger/jsonparser v1.1.1 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
129129
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
130130
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
131131
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
132+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
133+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
132134
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
133135
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
134136
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=

internal/boxcli/env.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2023 Jetpack Technologies Inc and contributors. All rights reserved.
2+
// Use of this source code is governed by the license in the LICENSE file.
3+
4+
package boxcli
5+
6+
import (
7+
"path/filepath"
8+
9+
"github.com/joho/godotenv"
10+
"github.com/pkg/errors"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
// to be composed into xyzCmdFlags structs
15+
type envFlag struct {
16+
env map[string]string
17+
envFile string
18+
}
19+
20+
func (f *envFlag) register(cmd *cobra.Command) {
21+
cmd.PersistentFlags().StringToStringVarP(
22+
&f.env, "env", "e", nil, "environment variables to set in the devbox environment",
23+
)
24+
cmd.PersistentFlags().StringVar(
25+
&f.envFile, "env-file", "", "path to a file containing environment variables to set in the devbox environment",
26+
)
27+
}
28+
29+
func (f *envFlag) Env(path string) (map[string]string, error) {
30+
envs := map[string]string{}
31+
var err error
32+
if f.envFile != "" {
33+
envPath := f.envFile
34+
if !filepath.IsAbs(envPath) {
35+
envPath = filepath.Join(path, envPath)
36+
}
37+
envs, err = godotenv.Read(envPath)
38+
if err != nil {
39+
return nil, errors.WithStack(err)
40+
}
41+
}
42+
43+
for k, v := range f.env {
44+
envs[k] = v
45+
}
46+
47+
return envs, nil
48+
}

internal/boxcli/run.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
)
2121

2222
type runCmdFlags struct {
23+
envFlag
2324
config configFlags
2425
pure bool
2526
listScripts bool
@@ -43,6 +44,7 @@ func runCmd() *cobra.Command {
4344
},
4445
}
4546

47+
flags.envFlag.register(command)
4648
flags.config.register(command)
4749
command.Flags().BoolVar(
4850
&flags.pure, "pure", false, "If this flag is specified, devbox runs the script in an isolated environment inheriting almost no variables from the current environment. A few variables, in particular HOME, USER and DISPLAY, are retained.")
@@ -90,11 +92,16 @@ func runScriptCmd(cmd *cobra.Command, args []string, flags runCmdFlags) error {
9092
debug.Log("script: %s", script)
9193
debug.Log("script args: %v", scriptArgs)
9294

95+
env, err := flags.Env(path)
96+
if err != nil {
97+
return err
98+
}
9399
// Check the directory exists.
94100
box, err := devbox.Open(&devopt.Opts{
95101
Dir: path,
96102
Writer: cmd.ErrOrStderr(),
97103
Pure: flags.pure,
104+
Env: env,
98105
})
99106
if err != nil {
100107
return redact.Errorf("error reading devbox.json: %w", err)

internal/boxcli/services.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
)
1212

1313
type servicesCmdFlags struct {
14+
envFlag
1415
config configFlags
1516
}
1617

@@ -92,6 +93,7 @@ func servicesCmd() *cobra.Command {
9293
},
9394
}
9495

96+
flags.envFlag.register(servicesCommand)
9597
flags.config.registerPersistent(servicesCommand)
9698
serviceUpFlags.register(upCommand)
9799
serviceStopFlags.register(stopCommand)
@@ -116,8 +118,13 @@ func listServices(cmd *cobra.Command, flags servicesCmdFlags) error {
116118
}
117119

118120
func startServices(cmd *cobra.Command, services []string, flags servicesCmdFlags) error {
121+
env, err := flags.Env(flags.config.path)
122+
if err != nil {
123+
return err
124+
}
119125
box, err := devbox.Open(&devopt.Opts{
120126
Dir: flags.config.path,
127+
Env: env,
121128
Writer: cmd.ErrOrStderr(),
122129
})
123130
if err != nil {
@@ -133,8 +140,13 @@ func stopServices(
133140
servicesFlags servicesCmdFlags,
134141
flags serviceStopFlags,
135142
) error {
143+
env, err := servicesFlags.Env(servicesFlags.config.path)
144+
if err != nil {
145+
return err
146+
}
136147
box, err := devbox.Open(&devopt.Opts{
137148
Dir: servicesFlags.config.path,
149+
Env: env,
138150
Writer: cmd.ErrOrStderr(),
139151
})
140152
if err != nil {
@@ -151,8 +163,13 @@ func restartServices(
151163
services []string,
152164
flags servicesCmdFlags,
153165
) error {
166+
env, err := flags.Env(flags.config.path)
167+
if err != nil {
168+
return err
169+
}
154170
box, err := devbox.Open(&devopt.Opts{
155171
Dir: flags.config.path,
172+
Env: env,
156173
Writer: cmd.ErrOrStderr(),
157174
})
158175
if err != nil {
@@ -168,8 +185,13 @@ func startProcessManager(
168185
servicesFlags servicesCmdFlags,
169186
flags serviceUpFlags,
170187
) error {
188+
env, err := servicesFlags.Env(servicesFlags.config.path)
189+
if err != nil {
190+
return err
191+
}
171192
box, err := devbox.Open(&devopt.Opts{
172193
Dir: servicesFlags.config.path,
194+
Env: env,
173195
CustomProcessComposeFile: flags.processComposeFile,
174196
Writer: cmd.ErrOrStderr(),
175197
})

internal/boxcli/shell.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
)
1717

1818
type shellCmdFlags struct {
19+
envFlag
1920
config configFlags
2021
printEnv bool
2122
pure bool
@@ -42,13 +43,19 @@ func shellCmd() *cobra.Command {
4243
&flags.pure, "pure", false, "If this flag is specified, devbox creates an isolated shell inheriting almost no variables from the current environment. A few variables, in particular HOME, USER and DISPLAY, are retained.")
4344

4445
flags.config.register(command)
46+
flags.envFlag.register(command)
4547
return command
4648
}
4749

4850
func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error {
51+
env, err := flags.Env(flags.config.path)
52+
if err != nil {
53+
return err
54+
}
4955
// Check the directory exists.
5056
box, err := devbox.Open(&devopt.Opts{
5157
Dir: flags.config.path,
58+
Env: env,
5259
Pure: flags.pure,
5360
Writer: cmd.ErrOrStderr(),
5461
})

internal/boxcli/shellenv.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
)
1313

1414
type shellEnvCmdFlags struct {
15+
envFlag
1516
config configFlags
1617
runInitHook bool
1718
install bool
@@ -45,17 +46,23 @@ func shellEnvCmd() *cobra.Command {
4546
&flags.pure, "pure", false, "If this flag is specified, devbox creates an isolated environment inheriting almost no variables from the current environment. A few variables, in particular HOME, USER and DISPLAY, are retained.")
4647

4748
flags.config.register(command)
49+
flags.envFlag.register(command)
4850

4951
command.AddCommand(shellEnvOnlyPathWithoutWrappersCmd())
5052

5153
return command
5254
}
5355

5456
func shellEnvFunc(cmd *cobra.Command, flags shellEnvCmdFlags) (string, error) {
57+
env, err := flags.Env(flags.config.path)
58+
if err != nil {
59+
return "", err
60+
}
5561
box, err := devbox.Open(&devopt.Opts{
5662
Dir: flags.config.path,
5763
Writer: cmd.ErrOrStderr(),
5864
Pure: flags.pure,
65+
Env: env,
5966
})
6067
if err != nil {
6168
return "", err

internal/impl/devbox.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const (
5353

5454
type Devbox struct {
5555
cfg *devconfig.Config
56+
env map[string]string
5657
lockfile *lock.File
5758
nix nix.Nixer
5859
projectDir string
@@ -84,6 +85,7 @@ func Open(opts *devopt.Opts) (*Devbox, error) {
8485

8586
box := &Devbox{
8687
cfg: cfg,
88+
env: opts.Env,
8789
nix: &nix.Nix{},
8890
projectDir: projectDir,
8991
pluginManager: plugin.NewManager(),
@@ -881,6 +883,10 @@ func (d *Devbox) computeNixEnv(ctx context.Context, usePrintDevEnvCache bool) (m
881883
env["XDG_DATA_DIRS"] = JoinPathLists(env["XDG_DATA_DIRS"], os.Getenv("XDG_DATA_DIRS"))
882884
}
883885

886+
for k, v := range d.env {
887+
env[k] = v
888+
}
889+
884890
return env, d.addHashToEnv(env)
885891
}
886892

internal/impl/devopt/devboxopts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
type Opts struct {
88
AllowInsecureAdds bool
99
Dir string
10+
Env map[string]string
1011
Pure bool
1112
IgnoreWarnings bool
1213
CustomProcessComposeFile string

0 commit comments

Comments
 (0)