Skip to content

Commit 2b8c495

Browse files
authored
[script-exit-on-error] disable for init-hooks (#1493)
## Summary @Lagoja identified an issue with scripts-exit-on-error. We source init-hooks into the host shell. So, `set -e` will get set in the host shell. Any subsequent error will cause the shell to exit (error may be from the init-hook, or later in the shell). For now, this PR disables this feature entirely for init hooks. We'll revisit this later: #1494 Also, this PR undoes the previous change to restrict this feature to fish-shells, since that only applied to init-hooks. Regular Devbox scripts always run in `sh`. ## How was it tested? testscript unit-tests did a sanity check that regular init_hooks work.
1 parent fbdbf01 commit 2b8c495

File tree

3 files changed

+36
-40
lines changed

3 files changed

+36
-40
lines changed

internal/impl/devbox.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,6 @@ func (d *Devbox) Shell(ctx context.Context) error {
210210
return shell.Run()
211211
}
212212

213-
// IsUserShellFish returns true if the user's shell is fish.
214-
// This wrapper function over DevboxShell enables querying from other packages that
215-
// make a devboxer interface.
216-
func (d *Devbox) IsUserShellFish() (bool, error) {
217-
sh, err := NewDevboxShell(d)
218-
if err != nil {
219-
return false, err
220-
}
221-
return sh.IsFish(), nil
222-
}
223-
224213
func (d *Devbox) RunScript(ctx context.Context, cmdName string, cmdArgs []string) error {
225214
ctx, task := trace.NewTask(ctx, "devboxRun")
226215
defer task.End()

internal/impl/shell.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,6 @@ func (s *DevboxShell) Run() error {
269269
return errors.WithStack(err)
270270
}
271271

272-
// IsFish returns whether this DevboxShell wraps a fish shell. Fish shells are non-posix compatible,
273-
// and so sometimes we may need to switch logic based on this function's result.
274-
func (s *DevboxShell) IsFish() bool {
275-
return s.name == shFish
276-
}
277-
278272
func (s *DevboxShell) shellRCOverrides(shellrc string) (extraEnv map[string]string, extraArgs []string) {
279273
// Shells have different ways of overriding the shellrc, so we need to
280274
// look at the name to know which env vars or args to set when launching the shell.
@@ -325,7 +319,7 @@ func (s *DevboxShell) writeDevboxShellrc() (path string, err error) {
325319
}()
326320

327321
tmpl := shellrcTmpl
328-
if s.IsFish() {
322+
if s.name == shFish {
329323
tmpl = fishrcTmpl
330324
}
331325

internal/shellgen/scripts.go

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ type devboxer interface {
2525
Lockfile() *lock.File
2626
AllInstallablePackages() ([]*devpkg.Package, error)
2727
InstallablePackages() []*devpkg.Package
28-
IsUserShellFish() (bool, error)
2928
PluginManager() *plugin.Manager
3029
ProjectDir() string
3130
}
@@ -53,7 +52,7 @@ func WriteScriptsToFiles(devbox devboxer) error {
5352
}
5453
hooks := strings.Join(append(pluginHooks, devbox.Config().InitHook().String()), "\n\n")
5554
// always write it, even if there are no hooks, because scripts will source it.
56-
err = WriteScriptFile(devbox, HooksFilename, hooks)
55+
err = writeHookFile(devbox, hooks)
5756
if err != nil {
5857
return errors.WithStack(err)
5958
}
@@ -82,39 +81,53 @@ func WriteScriptsToFiles(devbox devboxer) error {
8281
return nil
8382
}
8483

85-
func WriteScriptFile(devbox devboxer, name string, body string) (err error) {
86-
script, err := os.Create(ScriptPath(devbox.ProjectDir(), name))
84+
func writeHookFile(devbox devboxer, body string) (err error) {
85+
script, err := createScriptFile(devbox, HooksFilename)
8786
if err != nil {
8887
return errors.WithStack(err)
8988
}
90-
defer func() {
91-
cerr := script.Close()
92-
if err == nil {
93-
err = cerr
94-
}
95-
}()
96-
err = script.Chmod(0755)
89+
defer script.Close() // best effort: close file
90+
91+
_, err = script.WriteString(body)
92+
return errors.WithStack(err)
93+
}
94+
95+
func WriteScriptFile(devbox devboxer, name string, body string) (err error) {
96+
script, err := createScriptFile(devbox, name)
9797
if err != nil {
9898
return errors.WithStack(err)
9999
}
100+
defer script.Close() // best effort: close file
100101

101102
if featureflag.ScriptExitOnError.Enabled() {
102-
// Fish cannot run scripts with `set -e`.
103-
// NOTE: Devbox scripts will run using `sh` for consistency. However,
104-
// init_hooks in a fish shell will run using `fish` shell, and need this
105-
// check.
106-
isFish, err := devbox.IsUserShellFish()
107-
if err != nil {
108-
return errors.WithStack(err)
109-
}
110-
if !isFish {
111-
body = fmt.Sprintf("set -e\n\n%s", body)
112-
}
103+
// NOTE: Devbox scripts will run using `sh` for consistency.
104+
// However, we need to disable this for `fish` shell if/when we allow this for init_hooks,
105+
// since init_hooks run in the host shell, and not `sh`.
106+
body = fmt.Sprintf("set -e\n\n%s", body)
113107
}
114108
_, err = script.WriteString(body)
115109
return errors.WithStack(err)
116110
}
117111

112+
func createScriptFile(devbox devboxer, name string) (script *os.File, err error) {
113+
script, err = os.Create(ScriptPath(devbox.ProjectDir(), name))
114+
if err != nil {
115+
return nil, errors.WithStack(err)
116+
}
117+
defer func() {
118+
// best effort: close file if there was some subsequent error
119+
if err != nil {
120+
_ = script.Close()
121+
}
122+
}()
123+
124+
err = script.Chmod(0755)
125+
if err != nil {
126+
return nil, errors.WithStack(err)
127+
}
128+
return script, nil
129+
}
130+
118131
func ScriptPath(projectDir, scriptName string) string {
119132
return filepath.Join(projectDir, scriptsDir, scriptName+".sh")
120133
}

0 commit comments

Comments
 (0)