diff --git a/cmd/create.go b/cmd/create.go index abfb7c6cc..743555448 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -20,7 +20,7 @@ var ( ) func init() { - createCmd.PersistentFlags().StringVarP(&createConfigPath, "config", "c", constants.ZeroProjectYml, "config path") + createCmd.PersistentFlags().StringVarP(&createConfigPath, "config", "c", constants.ZeroProjectYml, "The project.yml file to load. The default is the one in the current directory.") createCmd.PersistentFlags().BoolVarP(&overwriteFiles, "overwrite", "o", false, "overwrite pre-existing files") rootCmd.AddCommand(createCmd) diff --git a/go.mod b/go.mod index 1e40008e8..42cf9e28b 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( github.com/aws/aws-sdk-go v1.30.12 + github.com/buger/goterm v1.0.0 github.com/coreos/go-semver v0.2.0 github.com/gabriel-vasile/mimetype v1.1.1 github.com/google/go-cmp v0.3.1 @@ -12,24 +13,24 @@ require ( github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/terraform v0.12.26 github.com/iancoleman/strcase v0.1.2 - github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect + github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 // indirect github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/k0kubun/pp v3.0.1+incompatible github.com/kyokomi/emoji v2.1.0+incompatible github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/machinebox/graphql v0.2.2 - github.com/manifoldco/promptui v0.3.0 + github.com/manifoldco/promptui v0.8.0 github.com/matryer/is v1.3.0 // indirect - github.com/mattn/go-colorable v0.1.2 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.13 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.2.0 github.com/spf13/cobra v0.0.6 github.com/stretchr/testify v1.5.1 github.com/termie/go-shutil v0.0.0-20140729215957-bcacb06fecae golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect - golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.2.2 diff --git a/go.sum b/go.sum index 48554991f..22a7188bb 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/buger/goterm v1.0.0 h1:ZB6uUlY8+sjJyFGzz2WpRqX2XYPeXVgtZAOJMwOsTWM= +github.com/buger/goterm v1.0.0/go.mod h1:16STi3LquiscTIHA8SXUNKEa/Cnu4ZHBH8NsCaWgso0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= @@ -99,6 +101,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gabriel-vasile/mimetype v1.1.1 h1:qbN9MPuRf3bstHu9zkI9jDWNfH//9+9kHxr9oRBBBOA= github.com/gabriel-vasile/mimetype v1.1.1/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= @@ -222,6 +225,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5 h1:Q5klzs6BL5FkassBX65t+KkG0XjYcjxEm+GNcQAsuaw= +github.com/juju/ansiterm v0.0.0-20210706145210-9283cdf370b5/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= @@ -254,27 +259,29 @@ github.com/likexian/simplejson-go v0.0.0-20190419151922-c1f9f0b4f084/go.mod h1:U github.com/likexian/simplejson-go v0.0.0-20190502021454-d8787b4bfa0b/go.mod h1:3BWwtmKP9cXWwYCr5bkoVDEfLywacOv0s06OBEDpyt8= github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 h1:im9kkmH0WWwxzegiv18gSUJbuXR9y028rXrWuPp6Jug= github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lusis/go-artifactory v0.0.0-20160115162124-7e4ce345df82/go.mod h1:y54tfGmO3NKssKveTEFFzH8C/akrSOy/iW9qEAUDV84= github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/manifoldco/promptui v0.3.0 h1:vJiVJREqDfn9ZhqTG1Dz5zP9RPWlAzWQkwRYLGyUHx4= -github.com/manifoldco/promptui v0.3.0/go.mod h1:zoCNXiJnyM03LlBgTsWv8mq28s7aTC71UgKasqRJHww= +github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= +github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20190223112901-5e5c9a7fe54b/go.mod h1:wr1VqkwW0AB5JS0QLy5GpVMS9E3VtRoSYXUYyVk46KY= github.com/matryer/is v1.3.0 h1:9qiso3jaJrOe6qBRJRBt2Ldht05qDiFP9le0JOIhRSI= github.com/matryer/is v1.3.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.4/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -447,6 +454,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -458,8 +466,12 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/internal/generate/generate_modules.go b/internal/generate/generate_modules.go index 5c32bd06a..5365ec4a7 100644 --- a/internal/generate/generate_modules.go +++ b/internal/generate/generate_modules.go @@ -39,7 +39,7 @@ func Generate(projectConfig projectconfig.ZeroProjectConfig, overwriteFiles bool // Load module configuration moduleConfig, err := module.ParseModuleConfig(mod.Files.Source) if err != nil { - return fmt.Errorf("unable to load module: %v", err) + return fmt.Errorf("unable to load module (%s): %v", mod.Files.Source, err) } moduleDir := path.Join(module.GetSourceDir(mod.Files.Source), moduleConfig.InputDir) diff --git a/internal/init/init.go b/internal/init/init.go index a32b7619f..d92f0aa7e 100644 --- a/internal/init/init.go +++ b/internal/init/init.go @@ -89,7 +89,7 @@ func loadAllModules(moduleSources []string) (map[string]moduleconfig.ModuleConfi for _, moduleSource := range moduleSources { mod, err := module.ParseModuleConfig(moduleSource) if err != nil { - exit.Fatal("Unable to load module: %v\n", err) + exit.Fatal("Unable to load module (%s): %v\n", moduleSource, err) } modules[mod.Name] = mod mappedSources[mod.Name] = moduleSource @@ -104,6 +104,7 @@ func getProjectNamePrompt() PromptHandler { Parameter: moduleconfig.Parameter{ Field: "projectName", Label: "Project Name", + Info: "This name will be used in most of the resources that are created and should be unique within an AWS account.", Default: "", }, Condition: NoCondition, @@ -117,6 +118,7 @@ func getProjectPrompts(projectName string, modules map[string]moduleconfig.Modul Parameter: moduleconfig.Parameter{ Field: "ShouldPushRepositories", Label: "Should the created projects be checked into github automatically?", + Info: "If yes, we will automatically create repositories for you in github and check in the generated code.\nIf no, you will need to do these steps manually after running the zero create command.", Options: yaml.MapSlice{ yaml.MapItem{Key: "y", Value: "yes"}, yaml.MapItem{Key: "n", Value: "no"}, @@ -129,6 +131,7 @@ func getProjectPrompts(projectName string, modules map[string]moduleconfig.Modul Parameter: moduleconfig.Parameter{ Field: "GithubRootOrg", Label: "What's the root of the github org to create repositories in?", + Info: "This should be github.com/", Default: "github.com/", }, Condition: KeyMatchCondition("ShouldPushRepositories", "y"), @@ -143,6 +146,7 @@ func getProjectPrompts(projectName string, modules map[string]moduleconfig.Modul Parameter: moduleconfig.Parameter{ Field: moduleName, Label: label, + Info: "This will be used as the name of the repository.", Default: module.OutputDir, }, Condition: NoCondition, @@ -171,8 +175,10 @@ func chooseCloudProvider(projectConfig *projectconfig.ZeroProjectConfig) { } func chooseStack(reg registry.Registry) []string { + showInfoBox("A stack is a group of Zero modules. They will be pulled in from the registry and templated to create the different parts of your project such as infrastructure, backend, frontend, etc.") + providerPrompt := promptui.Select{ - Label: "Pick a stack you'd like to use", + Label: "Pick the stack you'd like to use", Items: registry.AvailableLabels(reg), } _, providerResult, err := providerPrompt.Run() diff --git a/internal/init/prompts.go b/internal/init/prompts.go index 083b0c60b..ac40b248b 100644 --- a/internal/init/prompts.go +++ b/internal/init/prompts.go @@ -9,6 +9,7 @@ import ( "regexp" "strings" + tm "github.com/buger/goterm" "github.com/commitdev/zero/internal/config/moduleconfig" "github.com/commitdev/zero/internal/constants" "github.com/commitdev/zero/internal/util" @@ -100,6 +101,19 @@ func ValidateProjectName(input string) error { return nil } +const infoBoxHeight = 4 + +var currentLine int = infoBoxHeight + +// showInfoBox prints a box with some text in it, and the title "Info" +func showInfoBox(infoText string) { + box := tm.NewBox(100|tm.PCT, 4, 0) + fmt.Fprint(box, infoText) + tm.Print(tm.MoveTo(box.String(), 1, 1)) + tm.MoveCursor(4, 1) + tm.Printf("Info") +} + // RunPrompt obtains the value of PromptHandler depending on the parameter's definition // for the project config, there are multiple ways of obtaining the value // values go into params depending on `Condition` as the highest precedence (Whether it gets this value) @@ -113,9 +127,13 @@ func (p PromptHandler) RunPrompt(projectParams map[string]string, envVarTranslat var result string if p.Condition(projectParams) { - if p.Parameter.Info != "" { - flog.Guidef(p.Parameter.Info) + + // If we start printing below the bottom of the terminal screen, go back to the top + if currentLine+infoBoxHeight+1 > tm.Height() { + tm.Clear() + currentLine = infoBoxHeight } + // TODO: figure out scope of projectParams per project // potentially dangerous to have cross module env leaking // so if community module has an `execute: twitter tweet $ENV` @@ -127,6 +145,12 @@ func (p PromptHandler) RunPrompt(projectParams map[string]string, envVarTranslat } else if p.Parameter.Value != "" { result = p.Parameter.Value } else { + showInfoBox(p.Parameter.Info) + // Move down to the next line to show the prompt + currentLine++ + tm.MoveCursor(1, currentLine) + tm.Flush() // Call it every time at the end of rendering + err, result = promptParameter(p) } if err != nil { diff --git a/internal/init/prompts_test.go b/internal/init/prompts_test.go index 75fbe5f1b..5927cdc19 100644 --- a/internal/init/prompts_test.go +++ b/internal/init/prompts_test.go @@ -17,7 +17,7 @@ func TestGetParam(t *testing.T) { t.Run("Should execute params without prompt", func(t *testing.T) { param := moduleconfig.Parameter{ Field: "account-id", - Execute: "echo \"my-acconut-id\"", + Execute: "echo \"my-account-id\"", } prompt := initPrompts.PromptHandler{ @@ -27,7 +27,7 @@ func TestGetParam(t *testing.T) { } prompt.RunPrompt(projectParams, envVarTranslationMap) - assert.Equal(t, "my-acconut-id", projectParams[param.Field]) + assert.Equal(t, "my-account-id", projectParams[param.Field]) }) t.Run("executes with project context", func(t *testing.T) {