github.com/saucelabs/saucectl@v0.175.1/internal/saucecloud/cypress.go (about)

     1  package saucecloud
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/rs/zerolog/log"
     9  	"github.com/saucelabs/saucectl/internal/cypress"
    10  	"github.com/saucelabs/saucectl/internal/cypress/suite"
    11  	"github.com/saucelabs/saucectl/internal/framework"
    12  	"github.com/saucelabs/saucectl/internal/job"
    13  	"github.com/saucelabs/saucectl/internal/msg"
    14  )
    15  
    16  // CypressRunner represents the Sauce Labs cloud implementation for cypress.
    17  type CypressRunner struct {
    18  	CloudRunner
    19  	Project cypress.Project
    20  }
    21  
    22  // RunProject runs the tests defined in cypress.Project.
    23  func (r *CypressRunner) RunProject() (int, error) {
    24  	var deprecationMessage string
    25  	exitCode := 1
    26  
    27  	cyVersion := r.Project.GetVersion()
    28  	m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, cypress.Kind, cyVersion)
    29  	if err != nil {
    30  		r.logFrameworkError(err)
    31  		return exitCode, err
    32  	}
    33  	r.Project.SetVersion(m.FrameworkVersion)
    34  	if r.Project.GetRunnerVersion() == "" {
    35  		r.Project.SetRunnerVersion(m.CloudRunnerVersion)
    36  	}
    37  
    38  	if m.IsDeprecated() && !m.IsFlaggedForRemoval() {
    39  		deprecationMessage = r.deprecationMessage(cypress.Kind, cyVersion, m.RemovalDate)
    40  		fmt.Print(deprecationMessage)
    41  	}
    42  	if m.IsFlaggedForRemoval() {
    43  		deprecationMessage = r.flaggedForRemovalMessage(cypress.Kind, cyVersion)
    44  		fmt.Print(deprecationMessage)
    45  	}
    46  
    47  	for _, s := range r.Project.GetSuites() {
    48  		if s.PlatformName != "" && !framework.HasPlatform(m, s.PlatformName) {
    49  			msg.LogUnsupportedPlatform(s.PlatformName, framework.PlatformNames(m.Platforms))
    50  			return 1, errors.New("unsupported platform")
    51  		}
    52  	}
    53  
    54  	if err := r.validateTunnel(
    55  		r.Project.GetSauceCfg().Tunnel.Name,
    56  		r.Project.GetSauceCfg().Tunnel.Owner,
    57  		r.Project.IsDryRun(),
    58  		r.Project.GetSauceCfg().Tunnel.Timeout,
    59  	); err != nil {
    60  		return 1, err
    61  	}
    62  
    63  	app, otherApps, err := r.remoteArchiveProject(r.Project, r.Project.GetRootDir(), r.Project.GetSauceCfg().Sauceignore, r.Project.IsDryRun())
    64  	if err != nil {
    65  		return exitCode, err
    66  	}
    67  
    68  	if r.Project.IsDryRun() {
    69  		log.Info().Msgf("The following test suites would have run: [%s].", r.Project.GetSuiteNames())
    70  		return 0, nil
    71  	}
    72  
    73  	passed := r.runSuites(app, otherApps)
    74  	if passed {
    75  		exitCode = 0
    76  	}
    77  
    78  	if deprecationMessage != "" {
    79  		fmt.Print(deprecationMessage)
    80  	}
    81  
    82  	return exitCode, nil
    83  }
    84  
    85  func (r *CypressRunner) runSuites(app string, otherApps []string) bool {
    86  	sigChan := r.registerSkipSuitesOnSignal()
    87  	defer unregisterSignalCapture(sigChan)
    88  	jobOpts, results, err := r.createWorkerPool(r.Project.GetSauceCfg().Concurrency, r.Project.GetSauceCfg().Retries)
    89  	if err != nil {
    90  		return false
    91  	}
    92  	defer close(results)
    93  
    94  	suites := r.Project.GetSuites()
    95  	if r.Project.GetSauceCfg().LaunchOrder != "" {
    96  		history, err := r.getHistory(r.Project.GetSauceCfg().LaunchOrder)
    97  		if err != nil {
    98  			log.Warn().Err(err).Msg(msg.RetrieveJobHistoryError)
    99  		} else {
   100  			suites = suite.SortByHistory(suites, history)
   101  		}
   102  	}
   103  
   104  	// Submit suites to work on.
   105  	go func() {
   106  		for _, s := range suites {
   107  			smartRetry := r.Project.GetSmartRetry(s.Name)
   108  			jobOpts <- job.StartOptions{
   109  				ConfigFilePath:   r.Project.GetCfgPath(),
   110  				CLIFlags:         r.Project.GetCLIFlags(),
   111  				DisplayName:      s.Name,
   112  				Timeout:          s.Timeout,
   113  				App:              app,
   114  				OtherApps:        otherApps,
   115  				Suite:            s.Name,
   116  				Framework:        "cypress",
   117  				FrameworkVersion: r.Project.GetVersion(),
   118  				BrowserName:      s.Browser,
   119  				BrowserVersion:   s.BrowserVersion,
   120  				PlatformName:     s.PlatformName,
   121  				Name:             s.Name,
   122  				Build:            r.Project.GetSauceCfg().Metadata.Build,
   123  				Tags:             r.Project.GetSauceCfg().Metadata.Tags,
   124  				Tunnel: job.TunnelOptions{
   125  					ID:     r.Project.GetSauceCfg().Tunnel.Name,
   126  					Parent: r.Project.GetSauceCfg().Tunnel.Owner,
   127  				},
   128  				ScreenResolution: s.ScreenResolution,
   129  				RunnerVersion:    r.Project.GetRunnerVersion(),
   130  				Experiments:      r.Project.GetSauceCfg().Experiments,
   131  				Attempt:          0,
   132  				Retries:          r.Project.GetSauceCfg().Retries,
   133  				TimeZone:         s.TimeZone,
   134  				Visibility:       r.Project.GetSauceCfg().Visibility,
   135  				PassThreshold:    s.PassThreshold,
   136  				SmartRetry: job.SmartRetry{
   137  					FailedOnly: smartRetry.IsRetryFailedOnly(),
   138  				},
   139  			}
   140  		}
   141  	}()
   142  
   143  	return r.collectResults(r.Project.GetArtifactsCfg().Download, results, r.Project.GetSuiteCount())
   144  }