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 }