github.com/saucelabs/saucectl@v0.175.1/internal/cmd/ini/cmd.go (about) 1 package ini 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "os" 8 "time" 9 10 "github.com/saucelabs/saucectl/internal/config" 11 "github.com/saucelabs/saucectl/internal/credentials" 12 "github.com/saucelabs/saucectl/internal/cypress" 13 "github.com/saucelabs/saucectl/internal/espresso" 14 "github.com/saucelabs/saucectl/internal/flags" 15 "github.com/saucelabs/saucectl/internal/http" 16 "github.com/saucelabs/saucectl/internal/imagerunner" 17 "github.com/saucelabs/saucectl/internal/msg" 18 "github.com/saucelabs/saucectl/internal/playwright" 19 "github.com/saucelabs/saucectl/internal/testcafe" 20 "github.com/saucelabs/saucectl/internal/xcuitest" 21 22 "github.com/AlecAivazis/survey/v2/terminal" 23 "github.com/fatih/color" 24 "github.com/spf13/cobra" 25 ) 26 27 var ( 28 initUse = "init" 29 initShort = "bootstrap project" 30 initLong = "bootstrap an existing project for Sauce Labs" 31 initExample = "saucectl init" 32 ) 33 34 var noPrompt = false 35 var regionName = "us-west-1" 36 37 type initConfig struct { 38 frameworkName string 39 frameworkVersion string 40 cypressConfigFile string 41 dockerImage string 42 app string 43 testApp string 44 otherApps []string 45 platformName string 46 browserName string 47 region string 48 artifactWhen config.When 49 artifactWhenStr string 50 device config.Device 51 emulator config.Emulator 52 simulator config.Simulator 53 deviceFlag flags.Device 54 emulatorFlag flags.Emulator 55 simulatorFlag flags.Simulator 56 concurrency int 57 workload string 58 playwrightProject string 59 testMatch []string 60 } 61 62 var ( 63 testComposerTimeout = 5 * time.Second 64 rdcTimeout = 5 * time.Second 65 restoTimeout = 5 * time.Second 66 ) 67 68 func Command(preRun func(cmd *cobra.Command, args []string)) *cobra.Command { 69 cmd := &cobra.Command{ 70 Use: initUse, 71 Short: initShort, 72 Long: initLong, 73 Example: initExample, 74 SilenceUsage: true, 75 TraverseChildren: true, 76 PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 77 if preRun != nil { 78 preRun(cmd, args) 79 } 80 81 err := http.CheckProxy() 82 if err != nil { 83 return fmt.Errorf("invalid HTTP_PROXY value") 84 } 85 return nil 86 }, 87 } 88 89 cmd.AddCommand( 90 CypressCmd(), 91 EspressoCmd(), 92 ImageRunnerCmd(), 93 PlaywrightCmd(), 94 TestCafeCmd(), 95 XCUITestCmd(), 96 ) 97 98 flags := cmd.PersistentFlags() 99 100 flags.BoolVar(&noPrompt, "no-prompt", false, "Disable interactive prompts.") 101 flags.StringVarP(®ionName, "region", "r", "", "Sauce Labs region. Options: us-west-1, eu-central-1.") 102 103 return cmd 104 } 105 106 // Run runs the command 107 func Run(cmd *cobra.Command, cfg *initConfig) error { 108 cfg.region = regionName 109 110 if noPrompt { 111 return noPromptMode(cmd, cfg) 112 } 113 stdio := terminal.Stdio{In: os.Stdin, Out: os.Stdout, Err: os.Stderr} 114 115 creds := credentials.Get() 116 if !creds.IsSet() { 117 var err error 118 creds, err = askCredentials(stdio) 119 if err != nil { 120 return err 121 } 122 if err = credentials.ToFile(creds); err != nil { 123 return err 124 } 125 } 126 127 var err error 128 if cfg.region == "" { 129 cfg.region, err = askRegion(stdio) 130 if err != nil { 131 return err 132 } 133 } 134 135 ini := newInitializer(stdio, creds, cfg) 136 137 err = ini.checkCredentials(regionName) 138 if err != nil { 139 return err 140 } 141 142 err = ini.configure() 143 if err != nil { 144 return err 145 } 146 147 ccy, err := ini.userService.Concurrency(context.Background()) 148 if err != nil { 149 println() 150 color.HiRed("Unable to determine your exact allowed concurrency.\n") 151 color.HiBlue("Using 1 as default value.\n") 152 println() 153 ccy.Org.Allowed.VDC = 1 154 } 155 cfg.concurrency = ccy.Org.Allowed.VDC 156 157 files, err := saveConfigurationFiles(cfg) 158 if err != nil { 159 return err 160 } 161 displaySummary(files) 162 displayExtraInfo(cfg.frameworkName) 163 return nil 164 } 165 166 func noPromptMode(cmd *cobra.Command, cfg *initConfig) error { 167 stdio := terminal.Stdio{In: os.Stdin, Out: os.Stdout, Err: os.Stderr} 168 creds := credentials.Get() 169 if !creds.IsSet() { 170 return errors.New(msg.EmptyCredentials) 171 } 172 if cfg.region == "" { 173 return errors.New(msg.MissingRegion) 174 } 175 176 ini := newInitializer(stdio, creds, cfg) 177 178 var errs []error 179 switch cfg.frameworkName { 180 case cypress.Kind: 181 errs = ini.initializeBatchCypress() 182 case espresso.Kind: 183 errs = ini.initializeBatchEspresso(cmd.Flags()) 184 case playwright.Kind: 185 errs = ini.initializeBatchPlaywright() 186 case testcafe.Kind: 187 errs = ini.initializeBatchTestcafe() 188 case xcuitest.Kind: 189 errs = ini.initializeBatchXcuitest(cmd.Flags()) 190 case imagerunner.Kind: 191 errs = ini.initializeBatchImageRunner() 192 default: 193 println() 194 color.HiRed("Invalid framework selected") 195 println() 196 return errors.New(msg.InvalidSelectedFramework) 197 } 198 if len(errs) > 0 { 199 fmt.Printf("%d errors occured:\n", len(errs)) 200 for _, err := range errs { 201 fmt.Printf("- %v\n", err) 202 } 203 return fmt.Errorf("%s: %d errors occured", cfg.frameworkName, len(errs)) 204 } 205 206 ccy, err := ini.userService.Concurrency(context.Background()) 207 if err != nil { 208 println() 209 color.HiRed("Unable to determine your exact allowed concurrency.\n") 210 color.HiBlue("Using 1 as default value.\n") 211 println() 212 ccy.Org.Allowed.VDC = 1 213 } 214 cfg.concurrency = ccy.Org.Allowed.VDC 215 216 files, err := saveConfigurationFiles(cfg) 217 if err != nil { 218 return err 219 } 220 displaySummary(files) 221 displayExtraInfo(cfg.frameworkName) 222 return nil 223 }