Skip to content

Commit b97a0e4

Browse files
authored
Merge pull request #1965 from FabianKramm/master
refactor: rename devCommand to runPipelineCommand
2 parents 0f2ae91 + 0be6247 commit b97a0e4

10 files changed

Lines changed: 129 additions & 15 deletions

File tree

cmd/overwrite_command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,5 @@ func NewOverwriteCmd(f factory.Factory, globalFlags *flags.GlobalFlags, command
6666

6767
func (cmd *OverwriteCmd) Run(f factory.Factory, args []string) error {
6868
devCtx := devspacecontext.NewContext(context.Background(), f.GetLog())
69-
return ExecuteCommand(devCtx.Context, cmd.Command, cmd.Variables, args, devCtx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin)
69+
return executeCommandWithAfter(devCtx.Context, cmd.Command, args, cmd.Variables, devCtx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin, devCtx.Log)
7070
}

cmd/run.go

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/loft-sh/devspace/pkg/devspace/plugin"
1212
"github.com/loft-sh/devspace/pkg/util/command"
1313
"github.com/loft-sh/devspace/pkg/util/exit"
14+
"github.com/loft-sh/devspace/pkg/util/interrupt"
1415
"github.com/loft-sh/devspace/pkg/util/log"
1516
"io"
1617
"mvdan.cc/sh/v3/interp"
@@ -158,11 +159,56 @@ func (cmd *RunCmd) RunRun(f factory.Factory, args []string) error {
158159
}
159160

160161
ctx = ctx.AsDependency(dep)
161-
return ExecuteConfigCommand(ctx.Context, ctx.Config, args[0], args[1:], ctx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin)
162+
commandConfig, err := findCommand(ctx.Config, args[0])
163+
if err != nil {
164+
return err
165+
}
166+
167+
return executeCommandWithAfter(ctx.Context, commandConfig, args[1:], ctx.Config.Variables(), ctx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin, ctx.Log)
168+
}
169+
170+
commandConfig, err := findCommand(ctx.Config, args[0])
171+
if err != nil {
172+
return err
173+
}
174+
175+
return executeCommandWithAfter(ctx.Context, commandConfig, args[1:], ctx.Config.Variables(), ctx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin, ctx.Log)
176+
}
177+
178+
func findCommand(config config.Config, name string) (*latest.CommandConfig, error) {
179+
// Find command
180+
if config.Config().Commands == nil || config.Config().Commands[name] == nil {
181+
return nil, errors.Errorf("couldn't find command '%s' in devspace config", name)
182+
}
183+
184+
return config.Config().Commands[name], nil
185+
}
186+
187+
func executeCommandWithAfter(ctx context.Context, command *latest.CommandConfig, args []string, variables map[string]interface{}, dir string, stdout io.Writer, stderr io.Writer, stdin io.Reader, log log.Logger) error {
188+
originalErr := interrupt.Global.Run(func() error {
189+
return ExecuteCommand(ctx, command, variables, args, dir, stdout, stderr, stdin)
190+
}, func() {
191+
if command.After != "" {
192+
vars := variables
193+
vars["COMMAND_INTERRUPT"] = "true"
194+
err := executeShellCommand(ctx, command.After, vars, args, dir, stdout, stderr, stdin)
195+
if err != nil {
196+
log.Errorf("error executing after command: %v", err)
197+
}
198+
}
199+
})
200+
if command.After != "" {
201+
vars := variables
202+
if originalErr != nil {
203+
vars["COMMAND_ERROR"] = originalErr.Error()
204+
}
205+
err := executeShellCommand(ctx, command.After, vars, args, dir, stdout, stderr, stdin)
206+
if err != nil {
207+
return errors.Wrap(err, "error executing after command")
208+
}
162209
}
163210

164-
// Execute command
165-
return ExecuteConfigCommand(ctx.Context, ctx.Config, args[0], args[1:], ctx.WorkingDir, cmd.Stdout, cmd.Stderr, os.Stdin)
211+
return originalErr
166212
}
167213

168214
func ParseArgs(cobraCmd *cobra.Command, globalFlags *flags.GlobalFlags, log log.Logger) ([]string, error) {
@@ -221,14 +267,25 @@ func LoadCommandsConfig(configLoader loader.ConfigLoader, configOptions *loader.
221267
WithConfig(commandsInterface), nil
222268
}
223269

224-
// ExecuteConfigCommand executes a command from the config
225-
func ExecuteConfigCommand(ctx context.Context, config config.Config, name string, args []string, dir string, stdout io.Writer, stderr io.Writer, stdin io.Reader) error {
226-
if config.Config().Commands == nil || config.Config().Commands[name] == nil {
227-
return errors.Errorf("couldn't find command '%s' in devspace config", name)
270+
func executeShellCommand(ctx context.Context, shellCommand string, variables map[string]interface{}, args []string, dir string, stdout io.Writer, stderr io.Writer, stdin io.Reader) error {
271+
extraEnv := map[string]string{}
272+
for k, v := range variables {
273+
extraEnv[k] = fmt.Sprintf("%v", v)
274+
}
275+
276+
// execute the command in a shell
277+
err := engine.ExecuteSimpleShellCommand(ctx, dir, stdout, stderr, stdin, extraEnv, shellCommand, args...)
278+
if err != nil {
279+
if status, ok := interp.IsExitStatus(err); ok {
280+
return &exit.ReturnCodeError{
281+
ExitCode: int(status),
282+
}
283+
}
284+
285+
return errors.Wrap(err, "execute command")
228286
}
229287

230-
cmd := config.Config().Commands[name]
231-
return ExecuteCommand(ctx, cmd, config.Variables(), args, dir, stdout, stderr, stdin)
288+
return nil
232289
}
233290

234291
// ExecuteCommand executes a command from the config

cmd/run_pipeline.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (cmd *RunPipelineCmd) Run(f factory.Factory, args []string) error {
103103
return err
104104
}
105105

106-
return runWithHooks(ctx, "devCommand", func() error {
106+
return runWithHooks(ctx, "runPipelineCommand", func() error {
107107
// Build and deploy images
108108
err = cmd.runCommand(ctx, f, configOptions, args[0])
109109
if err != nil {

e2e/tests/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,7 @@ var _ = DevSpaceDescribe("config", func() {
17371737

17381738
// check if variables were loaded correctly
17391739
fmt.Println(config.Variables())
1740-
framework.ExpectEqual(len(config.Variables()), 4+len(variable.AlwaysResolvePredefinedVars))
1740+
framework.ExpectEqual(len(config.Variables()), 3+len(variable.AlwaysResolvePredefinedVars))
17411741
framework.ExpectEqual(len(config.LocalCache().ListVars()), 1)
17421742
test1, _ := config.LocalCache().GetVar("TEST_1")
17431743
framework.ExpectEqual(test1, "test")

pkg/devspace/config/config.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ func (c *config) LocalCache() localcache.Cache {
8080
}
8181

8282
func (c *config) Variables() map[string]interface{} {
83-
return c.resolvedVariables
83+
newVariables := map[string]interface{}{}
84+
for k, v := range c.resolvedVariables {
85+
newVariables[k] = v
86+
}
87+
88+
return newVariables
8489
}
8590

8691
func (c *config) Path() string {

pkg/devspace/config/versions/latest/schema.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,12 @@ type CommandConfig struct {
13241324
// Command is the command that should be executed. For example: 'echo 123'
13251325
Command string `yaml:"command" json:"command"`
13261326

1327+
// After is executed after the command was run. It is executed also when
1328+
// the command was interrupted which will set the env variable COMMAND_INTERRUPT
1329+
// to true as well as when the command errored which will set the error string to
1330+
// COMMAND_ERROR.
1331+
After string `yaml:"after" json:"after"`
1332+
13271333
// DisableReplace signals DevSpace to not replace the default command. E.g.
13281334
// dev does not replace devspace dev.
13291335
DisableReplace bool `yaml:"disableReplace,omitempty" json:"disableReplace,omitempty"`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package commands
2+
3+
import (
4+
"mvdan.cc/sh/v3/interp"
5+
"strings"
6+
)
7+
8+
func IsEmpty(args []string) error {
9+
// its possible that there are 0 args
10+
// because bash will omit an empty string
11+
// as argument
12+
if len(args) > 1 {
13+
return interp.NewExitStatus(1)
14+
} else if len(args) == 0 {
15+
return interp.NewExitStatus(0)
16+
}
17+
18+
if strings.TrimSpace(args[0]) == "" {
19+
return interp.NewExitStatus(0)
20+
}
21+
return interp.NewExitStatus(1)
22+
}

pkg/devspace/pipeline/engine/basichandler/commands/is_equal.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,29 @@ package commands
22

33
import (
44
"mvdan.cc/sh/v3/interp"
5+
"strings"
56
)
67

78
func IsEqual(args []string) error {
8-
if len(args) != 2 {
9+
if len(args) > 2 {
910
return interp.NewExitStatus(1)
1011
}
1112

13+
// one of the arguments is an empty string
14+
if len(args) == 1 {
15+
if strings.TrimSpace(args[0]) == "" {
16+
return interp.NewExitStatus(0)
17+
}
18+
19+
return interp.NewExitStatus(1)
20+
}
21+
22+
// both arguments are empty strings
23+
if len(args) == 0 {
24+
return interp.NewExitStatus(0)
25+
}
26+
27+
// compare arguments
1228
if args[0] == args[1] {
1329
return interp.NewExitStatus(0)
1430
}

pkg/devspace/pipeline/engine/basichandler/commands/is_os.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import (
66
)
77

88
func IsOS(args []string) error {
9-
if len(args) != 1 {
9+
if len(args) > 1 {
10+
return interp.NewExitStatus(1)
11+
}
12+
13+
// is empty string?
14+
if len(args) == 0 {
1015
return interp.NewExitStatus(1)
1116
}
1217

pkg/devspace/pipeline/engine/basichandler/handler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ var BasicCommands = map[string]func(ctx context.Context, args []string) error{
2323
"is_equal": func(ctx context.Context, args []string) error {
2424
return enginecommands.IsEqual(args)
2525
},
26+
"is_empty": func(ctx context.Context, args []string) error {
27+
return enginecommands.IsEmpty(args)
28+
},
2629
"is_true": func(ctx context.Context, args []string) error {
2730
return enginecommands.IsTrue(args)
2831
},

0 commit comments

Comments
 (0)