Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize Help and Usage content for all commands and sub commands #914

Merged
merged 78 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f0b7b98
Merge atmos specific and terraform help documentation
samtholiya Dec 14, 2024
922ba49
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Dec 16, 2024
437e1d4
Add help for terraform
samtholiya Dec 17, 2024
87fd2fd
Updated help content
samtholiya Dec 23, 2024
d7cabbd
Merge branch 'main' of https://github.com/cloudposse/atmos into featu…
samtholiya Dec 23, 2024
95304aa
test fix for auto approve
samtholiya Dec 23, 2024
0f3f84e
Update message for invalid command
samtholiya Dec 24, 2024
c719d86
remove old help code
samtholiya Dec 24, 2024
891e5d2
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Dec 24, 2024
fba6986
testing if auto-approve should be with two -
samtholiya Dec 24, 2024
48fee23
Merge branch 'feature/dev-2821-atmos-terraform-help-should-also-show-…
samtholiya Dec 24, 2024
636fb16
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Dec 26, 2024
51bbb79
check error after executing old usage func
samtholiya Dec 26, 2024
7765e3f
Merge branch 'feature/dev-2821-atmos-terraform-help-should-also-show-…
samtholiya Dec 26, 2024
d0351a8
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Dec 27, 2024
0491db4
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Dec 30, 2024
ce5bef1
rebase help.go
samtholiya Dec 31, 2024
1d8fe0e
Fix terraform subcommand help
samtholiya Dec 31, 2024
a8d6345
Remove unwanted setHelpFunc
samtholiya Dec 31, 2024
ed8b9f8
terraform,helmfile empty sub command should redirect to help
samtholiya Dec 31, 2024
18a6d96
check errors for usage and help
samtholiya Dec 31, 2024
40b4dd3
Added space in between Native commands
samtholiya Dec 31, 2024
80c4b8a
Removed unwanted code
samtholiya Jan 2, 2025
6823379
Add consistent usage and help for all commands
samtholiya Jan 5, 2025
ea2732f
Removed unwanted help check
samtholiya Jan 5, 2025
9184a73
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Jan 5, 2025
5766d45
Fix atmos help
samtholiya Jan 5, 2025
18aaa77
Help should be in stdout terminal
samtholiya Jan 5, 2025
58cbac8
Merge branch 'main' into feature/dev-2821-atmos-terraform-help-should…
samtholiya Jan 5, 2025
b920974
fix terraform args
samtholiya Jan 6, 2025
22923fc
Merge branch 'feature/dev-2821-atmos-terraform-help-should-also-show-…
samtholiya Jan 6, 2025
7b56200
fixed terraform command
samtholiya Jan 6, 2025
c20c5a2
Merge branch 'main' of https://github.com/cloudposse/atmos into featu…
samtholiya Jan 7, 2025
33bd593
fix helm command
samtholiya Jan 9, 2025
08ab3de
Merge branch 'main' of https://github.com/cloudposse/atmos into featu…
samtholiya Jan 9, 2025
969d988
rearrange the help strings
samtholiya Jan 9, 2025
1d88c3b
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 9, 2025
e22e144
simplified the code
samtholiya Jan 9, 2025
a52e95a
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 9, 2025
9814e03
Updated version with the help and usage as per expectations
samtholiya Jan 11, 2025
94d2057
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 11, 2025
d1dc47c
fix atmos command usage
samtholiya Jan 12, 2025
2bf3eec
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 12, 2025
70a92c8
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 12, 2025
c1153f1
Fix atmos usage error assertion
samtholiya Jan 12, 2025
db89d5d
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 12, 2025
e6f9ba8
Add SubCommand Aliases:
samtholiya Jan 12, 2025
35c8182
Updated template to be more dynamic
samtholiya Jan 13, 2025
55c1362
use cobra.NoArgs instead
samtholiya Jan 13, 2025
6a893e9
fix atmos version command
samtholiya Jan 13, 2025
24e9ac4
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 13, 2025
73de411
update atmos test case
samtholiya Jan 13, 2025
d9c550b
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 13, 2025
e51577f
Fix help and add test cases
samtholiya Jan 14, 2025
e88e989
added more test cases
samtholiya Jan 14, 2025
b1e0b4b
filter commands added
samtholiya Jan 14, 2025
c74a2d4
fixed typo
samtholiya Jan 14, 2025
f4fe81c
removed unwanted function
samtholiya Jan 14, 2025
be6b4b5
remove duplicated test
samtholiya Jan 14, 2025
db28636
use existing theme color package
samtholiya Jan 15, 2025
3886d68
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 15, 2025
27d6ae0
use existing theme color package
samtholiya Jan 15, 2025
424f6c6
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 15, 2025
4780d79
Update cmd/cmd_utils.go
samtholiya Jan 15, 2025
bd91bef
Fix error message ux
samtholiya Jan 15, 2025
e7a8434
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 15, 2025
f1e2b9b
fix template
samtholiya Jan 15, 2025
36357af
fix usage test case for atmos terraform
samtholiya Jan 15, 2025
00c4357
fix atlantis help
samtholiya Jan 15, 2025
8fded4b
Add more test cases for atlantis
samtholiya Jan 15, 2025
c3a6b6e
fix atlantis command help and usage
samtholiya Jan 16, 2025
f504b75
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 16, 2025
33bdded
fix atlantis command help and usage
samtholiya Jan 16, 2025
c7ee7e7
Merge branch 'feature/dev-2896-incorrect-output-for-atmos-validate' o…
samtholiya Jan 16, 2025
c0a0891
Merge branch 'main' of https://github.com/cloudposse/atmos into featu…
samtholiya Jan 18, 2025
ac22b72
fix test and update golden screenshots
samtholiya Jan 18, 2025
9d5d407
fix tests for atmos help
samtholiya Jan 18, 2025
1858b86
Merge branch 'main' into feature/dev-2896-incorrect-output-for-atmos-…
samtholiya Jan 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/atlantis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var atlantisCmd = &cobra.Command{
Short: "Generate and manage Atlantis configurations",
Long: `Generate and manage Atlantis configurations that use Atmos under the hood to run Terraform workflows, bringing the power of Atmos to Atlantis for streamlined infrastructure automation.`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Args: cobra.NoArgs,
}

func init() {
Expand Down
1 change: 1 addition & 0 deletions cmd/atlantis_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var atlantisGenerateCmd = &cobra.Command{
Short: "Generate Atlantis configuration files",
Long: "This command generates configuration files to automate and streamline Terraform workflows with Atlantis.",
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Args: cobra.NoArgs,
}

func init() {
Expand Down
5 changes: 4 additions & 1 deletion cmd/atlantis_generate_repo_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ var atlantisGenerateRepoConfigCmd = &cobra.Command{
Long: "Generate the repository configuration file required for Atlantis to manage Terraform repositories.",
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Run: func(cmd *cobra.Command, args []string) {
handleHelpRequest(cmd, args)
if len(args) > 0 {
showUsageAndExit(cmd, args)
}
// Check Atmos configuration
checkAtmosConfig()

err := e.ExecuteAtlantisGenerateRepoConfigCmd(cmd, args)
if err != nil {
u.LogErrorAndExit(schema.AtmosConfiguration{}, err)
Expand Down
1 change: 1 addition & 0 deletions cmd/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var awsCmd = &cobra.Command{
Short: "Run AWS-specific commands for interacting with cloud resources",
Long: `This command allows interaction with AWS resources through various CLI commands.`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Args: cobra.NoArgs,
}

func init() {
Expand Down
1 change: 1 addition & 0 deletions cmd/aws_eks.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ You can use this command to interact with AWS EKS, including operations like con
For a list of available AWS EKS commands, refer to the Atmos documentation:
https://atmos.tools/cli/commands/aws/eks-update-kubeconfig`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Args: cobra.NoArgs,
}

func init() {
Expand Down
66 changes: 65 additions & 1 deletion cmd/cmd_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"time"

"github.com/samber/lo"
"github.com/spf13/cobra"

e "github.com/cloudposse/atmos/internal/exec"
Expand Down Expand Up @@ -441,7 +442,7 @@ func checkAtmosConfig(opts ...AtmosValidateOption) {
atmosConfigExists, err := u.IsDirectory(atmosConfig.StacksBaseAbsolutePath)
if !atmosConfigExists || err != nil {
printMessageForMissingAtmosConfig(atmosConfig)
os.Exit(0)
os.Exit(1)
}
}
}
Expand Down Expand Up @@ -543,3 +544,66 @@ func CheckForAtmosUpdateAndPrintMessage(atmosConfig schema.AtmosConfiguration) {
func isVersionCommand() bool {
return len(os.Args) > 1 && os.Args[1] == "version"
}

// handleHelpRequest shows help content and exits only if the first argument is "help" or "--help" or "-h"
func handleHelpRequest(cmd *cobra.Command, args []string) {
if (len(args) > 0 && args[0] == "help") || Contains(args, "--help") || Contains(args, "-h") {
cmd.Help()
os.Exit(0)
samtholiya marked this conversation as resolved.
Show resolved Hide resolved
}
}

func showUsageAndExit(cmd *cobra.Command, args []string) {

var suggestions []string
unknownCommand := fmt.Sprintf("Error: Unknown command: %q\n\n", cmd.CommandPath())

if len(args) > 0 {
suggestions = cmd.SuggestionsFor(args[0])
unknownCommand = fmt.Sprintf("Error: Unknown command %q for %q\n\n", args[0], cmd.CommandPath())
}
u.PrintErrorInColor(unknownCommand)
if len(suggestions) > 0 {
u.PrintMessage("Did you mean this?")
for _, suggestion := range suggestions {
u.PrintMessage(fmt.Sprintf(" %s\n", suggestion))
}
} else {
// Retrieve valid subcommands dynamically
validSubcommands := []string{}
for _, subCmd := range cmd.Commands() {
validSubcommands = append(validSubcommands, subCmd.Name())
}
if len(validSubcommands) > 0 {
u.PrintMessage("Valid subcommands are:")
for _, sub := range validSubcommands {
u.PrintMessage(fmt.Sprintf(" %s", sub))
}
} else {
u.PrintMessage("No valid subcommands found")
}
}
u.PrintMessage(fmt.Sprintf("\nRun '%s --help' for usage", cmd.CommandPath()))
os.Exit(1)
}

// getConfigAndStacksInfo gets the
func getConfigAndStacksInfo(commandName string, cmd *cobra.Command, args []string) schema.ConfigAndStacksInfo {
// Check Atmos configuration
checkAtmosConfig()

var argsAfterDoubleDash []string
var finalArgs = args

doubleDashIndex := lo.IndexOf(args, "--")
if doubleDashIndex > 0 {
finalArgs = lo.Slice(args, 0, doubleDashIndex)
argsAfterDoubleDash = lo.Slice(args, doubleDashIndex+1, len(args))
}

info, err := e.ProcessCommandLineArgs(commandName, cmd, finalArgs, argsAfterDoubleDash)
if err != nil {
u.LogErrorAndExit(schema.AtmosConfiguration{}, err)
}
return info
}
234 changes: 234 additions & 0 deletions cmd/colored/colored.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// ColoredCobra allows you to colorize Cobra's text output,
// making it look better using simple settings to customize
// individual parts of console output.
//
// Usage example:
//
// 1. Insert in cmd/root.go file of your project :
//
// import cc "github.com/ivanpirog/coloredcobra"
//
// 2. Put the following code to the beginning of the Execute() function:
//
// cc.Init(&cc.Config{
// RootCmd: rootCmd,
// Headings: cc.Bold + cc.Underline,
// Commands: cc.Yellow + cc.Bold,
// ExecName: cc.Bold,
// Flags: cc.Bold,
// })
//
// 3. Build & execute your code.
//
// Copyright © 2022 Ivan Pirog <[email protected]>.
// Released under the MIT license.
// Project home: https://github.com/ivanpirog/coloredcobra
package colored

import (
"regexp"
"strings"

"github.com/cloudposse/atmos/pkg/ui/theme"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

// Config is a settings structure which sets styles for individual parts of Cobra text output.
//
// Note that RootCmd is required.
//
// Example:
//
// c := &cc.Config{
// RootCmd: rootCmd,
// }
type Config struct {
RootCmd *cobra.Command
NoExtraNewlines bool
NoBottomNewline bool
}

// Init patches Cobra's usage template with configuration provided.
func Init(cfg *Config) {

if cfg.RootCmd == nil {
panic("coloredcobra: Root command pointer is missing.")
}

// Get usage template
tpl := cfg.RootCmd.UsageTemplate()

//
// Add extra line breaks for headings
//
if !cfg.NoExtraNewlines {
tpl = strings.NewReplacer(
"Use \"", "\nUse \"",
).Replace(tpl)
}

//
// Styling headers
//
if theme.Styles.Help.Headings != nil {
ch := theme.Styles.Help.Headings
// Add template function to style the headers
cobra.AddTemplateFunc("HeadingStyle", ch.SprintFunc())
}

//
// Styling commands
//
if theme.Styles.Help.Commands != nil {
cc := theme.Styles.Help.Commands

// Add template function to style commands
cobra.AddTemplateFunc("CommandStyle", cc.SprintFunc())
cobra.AddTemplateFunc("sum", func(a, b int) int {
return a + b
})

// Patch usage template
re := regexp.MustCompile(`(?i){{\s*rpad\s+.Name\s+.NamePadding\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{rpad (CommandStyle .Name) (sum .NamePadding 12)}}")

re = regexp.MustCompile(`(?i){{\s*rpad\s+.CommandPath\s+.CommandPathPadding\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{rpad (CommandStyle .CommandPath) (sum .CommandPathPadding 12)}}")
}

//
// Styling a short desription of commands
//
if theme.Styles.Help.CmdShortDescr != nil {
csd := theme.Styles.Help.CmdShortDescr

cobra.AddTemplateFunc("CmdShortStyle", csd.SprintFunc())

re := regexp.MustCompile(`(?ism)({{\s*range\s+.Commands\s*}}.*?){{\s*.Short\s*}}`)
tpl = re.ReplaceAllString(tpl, `$1{{CmdShortStyle .Short}}`)
}

//
// Styling executable file name
//
if theme.Styles.Help.ExecName != nil {
cen := theme.Styles.Help.ExecName

// Add template functions
cobra.AddTemplateFunc("ExecStyle", cen.SprintFunc())
cobra.AddTemplateFunc("UseLineStyle", func(s string) string {
spl := strings.Split(s, " ")
spl[0] = cen.Sprint(spl[0])
return strings.Join(spl, " ")
})

// Patch usage template
re := regexp.MustCompile(`(?i){{\s*.CommandPath\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{ExecStyle .CommandPath}}")

re = regexp.MustCompile(`(?i){{\s*.UseLine\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{UseLineStyle .UseLine}}")
}

//
// Styling flags
//
var cf, cfd, cfdt *color.Color
if theme.Styles.Help.Flags != nil {
cf = theme.Styles.Help.Flags
}
if theme.Styles.Help.FlagsDescr != nil {
cfd = theme.Styles.Help.FlagsDescr
}
if theme.Styles.Help.FlagsDataType != nil {
cfdt = theme.Styles.Help.FlagsDataType
}
if cf != nil || cfd != nil || cfdt != nil {

cobra.AddTemplateFunc("FlagStyle", func(s string) string {

// Flags info section is multi-line.
// Let's split these lines and iterate them.
lines := strings.Split(s, "\n")
for k := range lines {

// Styling short and full flags (-f, --flag)
if cf != nil {
re := regexp.MustCompile(`(--?\S+)`)
for _, flag := range re.FindAllString(lines[k], 2) {
lines[k] = strings.Replace(lines[k], flag, cf.Sprint(flag), 1)
}
}

// If no styles for flag data types and description - continue
if cfd == nil && cfdt == nil {
continue
}

// Split line into two parts: flag data type and description
// Tip: Use debugger to understand the logic
re := regexp.MustCompile(`\s{2,}`)
spl := re.Split(lines[k], -1)
if len(spl) != 3 {
continue
}

// Styling the flag description
if cfd != nil {
lines[k] = strings.Replace(lines[k], spl[2], cfd.Sprint(spl[2]), 1)
}

// Styling flag data type
// Tip: Use debugger to understand the logic
if cfdt != nil {
re = regexp.MustCompile(`\s+(\w+)$`) // the last word after spaces is the flag data type
m := re.FindAllStringSubmatch(spl[1], -1)
if len(m) == 1 && len(m[0]) == 2 {
lines[k] = strings.Replace(lines[k], m[0][1], cfdt.Sprint(m[0][1]), 1)
}
}

}
s = strings.Join(lines, "\n")

return s

})

// Patch usage template
re := regexp.MustCompile(`(?i)(\.(InheritedFlags|LocalFlags)\.FlagUsages)`)
tpl = re.ReplaceAllString(tpl, "FlagStyle $1")
}

//
// Styling aliases
//
if theme.Styles.Help.Aliases != nil {
ca := theme.Styles.Help.Aliases
cobra.AddTemplateFunc("AliasStyle", ca.SprintFunc())

re := regexp.MustCompile(`(?i){{\s*.NameAndAliases\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{AliasStyle .NameAndAliases}}")
}

//
// Styling the example text
//
if theme.Styles.Help.Example != nil {
ce := theme.Styles.Help.Example
cobra.AddTemplateFunc("ExampleStyle", ce.SprintFunc())

re := regexp.MustCompile(`(?i){{\s*.Example\s*}}`)
tpl = re.ReplaceAllLiteralString(tpl, "{{ExampleStyle .Example}}")
}

// Adding a new line to the end
if !cfg.NoBottomNewline {
tpl += "\n"
}
// Apply patched template
cfg.RootCmd.SetUsageTemplate(tpl)
// Debug line, uncomment when needed
// fmt.Println(tpl)
}
Loading
Loading