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(&regionName, "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  }