Skip to content

Commit 1216639

Browse files
authored
Update the bash command execution to specify set -e when executing. (#155)
This PR allows for the innovation engine to correctly terminate a code block after any command inside of it has failed. Previously the innovation engine would rely on the last command in the code block being executed to check for & report failure which meant that code blocks which executed multiple commands would not fail if any command other than the last one had an error.
1 parent 03ae339 commit 1216639

File tree

2 files changed

+115
-3
lines changed

2 files changed

+115
-3
lines changed

internal/shells/bash.go

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ type BashCommandConfiguration struct {
129129
// Executes a bash command and returns the output or error.
130130
func ExecuteBashCommand(command string, config BashCommandConfiguration) (CommandOutput, error) {
131131
var commandWithStateSaved = []string{
132+
"set -e",
132133
command,
133134
"IE_LAST_COMMAND_EXIT_CODE=\"$?\"",
134135
"env > " + environmentStateFile,

internal/shells/bash_test.go

+114-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,13 @@ func TestEnvironmentVariableValidationAndFiltering(t *testing.T) {
5353
"_AnotherValidKey": "value2",
5454
}
5555

56-
if len(validEnvMap) != len(expectedValidEnvMap) {
57-
t.Errorf("Expected validEnvMap to have %d keys, got %d", len(expectedValidEnvMap), len(validEnvMap))
58-
}
56+
if len(validEnvMap) != len(expectedValidEnvMap) {
57+
t.Errorf(
58+
"Expected validEnvMap to have %d keys, got %d",
59+
len(expectedValidEnvMap),
60+
len(validEnvMap),
61+
)
62+
}
5963

6064
for key, value := range validEnvMap {
6165
if expectedValue, ok := expectedValidEnvMap[key]; !ok || value != expectedValue {
@@ -64,3 +68,110 @@ func TestEnvironmentVariableValidationAndFiltering(t *testing.T) {
6468
}
6569
})
6670
}
71+
72+
func TestBashCommandExecution(t *testing.T) {
73+
// Ensures that if a command succeeds, the output is returned.
74+
t.Run("Valid command execution", func(t *testing.T) {
75+
cmd := "printf hello"
76+
result, err := ExecuteBashCommand(
77+
cmd,
78+
BashCommandConfiguration{
79+
EnvironmentVariables: nil,
80+
InheritEnvironment: true,
81+
InteractiveCommand: false,
82+
WriteToHistory: false,
83+
},
84+
)
85+
if err != nil {
86+
t.Errorf("Expected err to be nil, got %v", err)
87+
}
88+
if result.StdOut != "hello" {
89+
t.Errorf("Expected result to be non-empty, got '%s'", result.StdOut)
90+
}
91+
})
92+
93+
// Ensures that if a command fails, an error is returned.
94+
t.Run("Invalid command execution", func(t *testing.T) {
95+
cmd := "not_real_command"
96+
_, err := ExecuteBashCommand(
97+
cmd,
98+
BashCommandConfiguration{
99+
EnvironmentVariables: nil,
100+
InheritEnvironment: true,
101+
InteractiveCommand: false,
102+
WriteToHistory: false,
103+
},
104+
)
105+
106+
if err == nil {
107+
t.Errorf("Expected an error to occur, but the command succeeded.")
108+
}
109+
110+
})
111+
112+
// Test the execution of commands with multiple subcommands.
113+
t.Run("Command with multiple subcommands", func(t *testing.T) {
114+
cmd := "printf hello; printf world"
115+
result, err := ExecuteBashCommand(
116+
cmd,
117+
BashCommandConfiguration{
118+
EnvironmentVariables: nil,
119+
InheritEnvironment: true,
120+
InteractiveCommand: false,
121+
WriteToHistory: false,
122+
},
123+
)
124+
if err != nil {
125+
t.Errorf("Expected err to be nil, got %v", err)
126+
}
127+
if result.StdOut != "helloworld" {
128+
t.Errorf("Expected result to be non-empty, got '%s'", result.StdOut)
129+
}
130+
})
131+
132+
// Ensures that if one of the subcommands fail, the other commands do
133+
// as well.
134+
t.Run("Command with multiple subcommands exits on first error", func(t *testing.T) {
135+
cmd := "printf hello; not_real_command; printf world"
136+
_, err := ExecuteBashCommand(
137+
cmd,
138+
BashCommandConfiguration{
139+
EnvironmentVariables: nil,
140+
InheritEnvironment: true,
141+
InteractiveCommand: false,
142+
WriteToHistory: false,
143+
},
144+
)
145+
146+
if err == nil {
147+
t.Errorf("Expected an error to occur, but the command succeeded.")
148+
}
149+
150+
})
151+
152+
// Ensures that commands can access environment variables passed into
153+
// the configuration.
154+
t.Run("Command with environment variables", func(t *testing.T) {
155+
cmd := "printf $TEST_ENV_VAR"
156+
result, err := ExecuteBashCommand(
157+
cmd,
158+
BashCommandConfiguration{
159+
EnvironmentVariables: map[string]string{
160+
"TEST_ENV_VAR": "hello",
161+
},
162+
InheritEnvironment: true,
163+
InteractiveCommand: false,
164+
WriteToHistory: false,
165+
},
166+
)
167+
168+
if err != nil {
169+
t.Errorf("Expected err to be nil, got %v", err)
170+
}
171+
172+
if result.StdOut != "hello" {
173+
t.Errorf("Expected result to be non-empty, got '%s'", result.StdOut)
174+
}
175+
})
176+
177+
}

0 commit comments

Comments
 (0)