Skip to content

Commit 59a666a

Browse files
RoseSecurityostermanaknysh
authored
feat: add spinner during atmos validate stacks operations (#1005)
* feat: add spinner during validate stacks operations * fix: regenerate tests for validating stacks --------- Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]> Co-authored-by: Andriy Knysh <[email protected]>
1 parent 2a38feb commit 59a666a

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

internal/exec/validate_stacks.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ import (
1111
"strings"
1212
"time"
1313

14+
"github.com/charmbracelet/bubbles/spinner"
15+
tea "github.com/charmbracelet/bubbletea"
1416
"github.com/hashicorp/go-getter"
1517
"github.com/pkg/errors"
1618
"github.com/spf13/cobra"
1719

1820
cfg "github.com/cloudposse/atmos/pkg/config"
1921
"github.com/cloudposse/atmos/pkg/schema"
22+
"github.com/cloudposse/atmos/pkg/ui/theme"
2023
u "github.com/cloudposse/atmos/pkg/utils"
2124
)
2225

@@ -27,28 +30,71 @@ const atmosManifestDefaultFileName = "schemas/atmos/atmos-manifest/1.0/atmos-man
2730

2831
// ExecuteValidateStacksCmd executes `validate stacks` command
2932
func ExecuteValidateStacksCmd(cmd *cobra.Command, args []string) error {
33+
// Initialize spinner
34+
message := "Validating Atmos Stacks..."
35+
s := spinner.New()
36+
s.Style = theme.Styles.Link
37+
38+
var opts []tea.ProgramOption
39+
if !CheckTTYSupport() {
40+
// Workaround for non-TTY environments
41+
opts = []tea.ProgramOption{tea.WithoutRenderer(), tea.WithInput(nil)}
42+
u.LogTrace("No TTY detected. Falling back to basic output. This can happen when no terminal is attached or when commands are pipelined.")
43+
fmt.Println(message)
44+
}
45+
46+
p := tea.NewProgram(modelSpinner{
47+
spinner: s,
48+
message: message,
49+
}, opts...)
50+
51+
// Use error channel to capture spinner errors
52+
spinnerDone := make(chan error, 1)
53+
54+
go func() {
55+
_, err := p.Run()
56+
if err != nil {
57+
fmt.Println(message)
58+
u.LogError(fmt.Errorf("failed to run spinner: %w", err))
59+
}
60+
spinnerDone <- err
61+
close(spinnerDone)
62+
}()
63+
64+
// Process CLI arguments
3065
info, err := ProcessCommandLineArgs("", cmd, args, nil)
3166
if err != nil {
67+
p.Quit()
68+
<-spinnerDone
3269
return err
3370
}
3471

3572
atmosConfig, err := cfg.InitCliConfig(info, true)
3673
if err != nil {
74+
p.Quit()
75+
<-spinnerDone
3776
return err
3877
}
3978

4079
flags := cmd.Flags()
41-
4280
schemasAtmosManifestFlag, err := flags.GetString("schemas-atmos-manifest")
4381
if err != nil {
82+
p.Quit()
83+
<-spinnerDone
4484
return err
4585
}
4686

4787
if schemasAtmosManifestFlag != "" {
4888
atmosConfig.Schemas.Atmos.Manifest = schemasAtmosManifestFlag
4989
}
5090

51-
return ValidateStacks(atmosConfig)
91+
err = ValidateStacks(atmosConfig)
92+
93+
// Ensure spinner is stopped before returning
94+
p.Quit()
95+
<-spinnerDone
96+
97+
return err
5298
}
5399

54100
// ValidateStacks validates Atmos stack configuration

tests/snapshots/TestCLICommands_atmos_validate_stacks_with_metadata.stdout.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)