Skip to content

Commit

Permalink
Show failed command after atmos workflow failure (#767)
Browse files Browse the repository at this point in the history
* add feature for failed commands workflow

* chore: clean code cmd msg

* fix: general fixes for workflow cmd output

* clean up error message

* move workflow error message

* move workflow msg

* remove cd command

---------

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>
  • Loading branch information
Cerebrovinny and osterman authored Dec 5, 2024
1 parent 31d7c5e commit 0ff08d5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 7 deletions.
5 changes: 4 additions & 1 deletion cmd/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ var workflowCmd = &cobra.Command{
Example: "atmos workflow\n" +
"atmos workflow <name> -f <file>\n" +
"atmos workflow <name> -f <file> -s <stack>\n" +
"atmos workflow <name> -f <file> --from-step <step-name>",
"atmos workflow <name> -f <file> --from-step <step-name>\n\n" +
"To resume the workflow from this step, run:\n" +
"atmos workflow deploy-infra -f workflow1 --from-step deploy-vpc\n\n" +
"For more details refer to https://atmos.tools/cli/commands/workflow/",
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Run: func(cmd *cobra.Command, args []string) {
err := e.ExecuteWorkflowCmd(cmd, args)
Expand Down
29 changes: 23 additions & 6 deletions internal/exec/workflow_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path"
"path/filepath"
"sort"
"strings"

Expand Down Expand Up @@ -70,11 +71,10 @@ func ExecuteWorkflow(
commandType = "atmos"
}

var err error
if commandType == "shell" {
commandName := fmt.Sprintf("%s-step-%d", workflow, stepIdx)
if err := ExecuteShell(cliConfig, command, commandName, ".", []string{}, dryRun); err != nil {
return err
}
err = ExecuteShell(cliConfig, command, commandName, ".", []string{}, dryRun)
} else if commandType == "atmos" {
args := strings.Fields(command)

Expand All @@ -101,12 +101,29 @@ func ExecuteWorkflow(
logFunc(cliConfig, fmt.Sprintf("Stack: %s", finalStack))
}

if err := ExecuteShellCommand(cliConfig, "atmos", args, ".", []string{}, dryRun, ""); err != nil {
return err
}
err = ExecuteShellCommand(cliConfig, "atmos", args, ".", []string{}, dryRun, "")
} else {
return fmt.Errorf("invalid workflow step type '%s'. Supported types are 'atmos' and 'shell'", commandType)
}

if err != nil {
workflowFileName := filepath.Base(workflowPath)
workflowFileName = strings.TrimSuffix(workflowFileName, filepath.Ext(workflowFileName))

failedMsg := color.New(color.FgRed).Sprintf("\nStep '%s' failed!", step.Name)

u.LogDebug(cliConfig, fmt.Sprintf("\nCommand failed: %s", command))
u.LogDebug(cliConfig, fmt.Sprintf("Error: %v", err))

resumeMsg := color.New(color.FgGreen).Sprintf(
"\nTo resume the workflow from this step, run:\natmos workflow %s -f %s --from-step %s",
workflow,
workflowFileName,
step.Name,
)

return fmt.Errorf("%s\n%s", failedMsg, resumeMsg)
}
}

return nil
Expand Down
34 changes: 34 additions & 0 deletions website/docs/core-concepts/workflows/workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,40 @@ The Atmos stack used by the workflow commands of type `atmos` can be specified i
atmos workflow my-workflow -f workflow1 -s tenant1-ue2-dev
```

## Workflow Failure Handling and Resume

When a workflow step fails, Atmos will:
1. Display which step failed
2. Show the exact command that failed
3. Provide a ready-to-use command to resume the workflow from the failed step

Given this workflow:

```yaml title="stacks/workflows/networking.yaml"
workflows:
provision-vpcs:
description: "Deploy vpc components"
steps:
- command: terraform plan vpc -s plat-ue2-dev
name: step-1
- command: terraform plan vpc -s plat-ue2-staging
name: step-2
- command: terraform plan vpc -s plat-ue2-prod
name: step-3
```

If step-2 fails, you'll see:

```console
Step 'step-2' failed!
Command failed:
terraform plan vpc -s plat-ue2-staging
To resume the workflow from this step, run:
atmos workflow provision-vpcs -f networking --from-step step-2
```

### Stack Precedence

The stack defined inline in the command itself has the lowest priority, it can and will be overridden by any other stack definition.
Expand Down

0 comments on commit 0ff08d5

Please sign in to comment.