From 8320e3ceafaad71c2fd46b5a61346346b12b1657 Mon Sep 17 00:00:00 2001 From: Tian Feng Date: Fri, 13 Sep 2024 14:08:46 -0700 Subject: [PATCH] feat: Capture sharding types and options (#949) * feat: Capture sharding type * add comments for GetShardOpts * revise espresso sharding value collection * rename functions and parameters * revert changes --- internal/cmd/run/cucumber.go | 2 +- internal/cmd/run/cypress.go | 2 +- internal/cmd/run/espresso.go | 2 +- internal/cmd/run/playwright.go | 2 +- internal/cmd/run/testcafe.go | 2 +- internal/cmd/run/xcuitest.go | 2 +- internal/cucumber/config.go | 24 ++++++++++++++++++++---- internal/cypress/config.go | 3 ++- internal/cypress/v1/config.go | 24 ++++++++++++++++++++---- internal/espresso/config.go | 19 +++++++++++++++---- internal/playwright/config.go | 27 +++++++++++++++++++++++---- internal/testcafe/config.go | 11 ++++++++--- internal/usage/tracker.go | 8 ++++++-- internal/xcuitest/config.go | 11 ++++++++--- 14 files changed, 108 insertions(+), 31 deletions(-) diff --git a/internal/cmd/run/cucumber.go b/internal/cmd/run/cucumber.go index 2e8404556..bb3cbeb48 100644 --- a/internal/cmd/run/cucumber.go +++ b/internal/cmd/run/cucumber.go @@ -106,7 +106,7 @@ func runCucumber(cmd *cobra.Command, isCLIDriven bool) (int, error) { props := usage.Properties{} props.SetFramework("playwright-cucumberjs").SetFVersion(p.Playwright.Version).SetFlags(cmd.Flags()).SetSauceConfig(p.Sauce). SetArtifacts(p.Artifacts).SetNPM(p.Npm).SetNumSuites(len(p.Suites)). - SetSlack(p.Notifications.Slack).SetSharding(cucumber.IsSharded(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). + SetSlack(p.Notifications.Slack).SetSharding(cucumber.GetShardTypes(p.Suites), cucumber.GetShardOpts(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.Reporters).SetNodeVersion(p.NodeVersion) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) _ = tracker.Close() diff --git a/internal/cmd/run/cypress.go b/internal/cmd/run/cypress.go index 99ef41128..4263be35d 100644 --- a/internal/cmd/run/cypress.go +++ b/internal/cmd/run/cypress.go @@ -140,7 +140,7 @@ func runCypress(cmd *cobra.Command, cflags cypressFlags, isCLIDriven bool) (int, props := usage.Properties{} props.SetFramework("cypress").SetFVersion(p.GetVersion()).SetFlags(cmd.Flags()).SetSauceConfig(p.GetSauceCfg()). SetArtifacts(p.GetArtifactsCfg()).SetNPM(p.GetNpm()).SetNumSuites(len(p.GetSuites())). - SetSlack(p.GetNotifications().Slack).SetSharding(p.IsSharded()).SetLaunchOrder(p.GetSauceCfg().LaunchOrder). + SetSlack(p.GetNotifications().Slack).SetSharding(p.GetShardTypes(), p.GetShardOpts()).SetLaunchOrder(p.GetSauceCfg().LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.GetReporters()).SetNodeVersion(p.GetNodeVersion()) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) diff --git a/internal/cmd/run/espresso.go b/internal/cmd/run/espresso.go index a32327540..400adaa02 100644 --- a/internal/cmd/run/espresso.go +++ b/internal/cmd/run/espresso.go @@ -122,7 +122,7 @@ func runEspresso(cmd *cobra.Command, espressoFlags espressoFlags, isCLIDriven bo props := usage.Properties{} props.SetFramework("espresso").SetFlags(cmd.Flags()).SetSauceConfig(p.Sauce).SetArtifacts(p.Artifacts). SetNumSuites(len(p.Suites)).SetSlack(p.Notifications.Slack). - SetSharding(espresso.IsSharded(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). + SetSharding(espresso.GetShardTypes(p.Suites), nil).SetLaunchOrder(p.Sauce.LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.Reporters) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) _ = tracker.Close() diff --git a/internal/cmd/run/playwright.go b/internal/cmd/run/playwright.go index cc5f81d11..85626a65c 100644 --- a/internal/cmd/run/playwright.go +++ b/internal/cmd/run/playwright.go @@ -152,7 +152,7 @@ func runPlaywright(cmd *cobra.Command, pf playwrightFlags, isCLIDriven bool) (in props := usage.Properties{} props.SetFramework("playwright").SetFVersion(p.Playwright.Version).SetFlags(cmd.Flags()).SetSauceConfig(p.Sauce). SetArtifacts(p.Artifacts).SetNPM(p.Npm).SetNumSuites(len(p.Suites)). - SetSlack(p.Notifications.Slack).SetSharding(playwright.IsSharded(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). + SetSlack(p.Notifications.Slack).SetSharding(playwright.GetShardTypes(p.Suites), playwright.GetShardOpts(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.Reporters).SetNodeVersion(p.NodeVersion) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) _ = tracker.Close() diff --git a/internal/cmd/run/testcafe.go b/internal/cmd/run/testcafe.go index 1e1cc4152..fccdf3631 100644 --- a/internal/cmd/run/testcafe.go +++ b/internal/cmd/run/testcafe.go @@ -175,7 +175,7 @@ func runTestcafe(cmd *cobra.Command, tcFlags testcafeFlags, isCLIDriven bool) (i props := usage.Properties{} props.SetFramework("testcafe").SetFVersion(p.Testcafe.Version).SetFlags(cmd.Flags()).SetSauceConfig(p.Sauce). SetArtifacts(p.Artifacts).SetNPM(p.Npm).SetNumSuites(len(p.Suites)). - SetSlack(p.Notifications.Slack).SetSharding(testcafe.IsSharded(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). + SetSlack(p.Notifications.Slack).SetSharding(testcafe.GetShardTypes(p.Suites), nil).SetLaunchOrder(p.Sauce.LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.Reporters).SetNodeVersion(p.NodeVersion) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) _ = tracker.Close() diff --git a/internal/cmd/run/xcuitest.go b/internal/cmd/run/xcuitest.go index d59d8d2ed..735a76787 100644 --- a/internal/cmd/run/xcuitest.go +++ b/internal/cmd/run/xcuitest.go @@ -122,7 +122,7 @@ func runXcuitest(cmd *cobra.Command, xcuiFlags xcuitestFlags, isCLIDriven bool) props := usage.Properties{} props.SetFramework("xcuitest").SetFlags(cmd.Flags()).SetSauceConfig(p.Sauce).SetArtifacts(p.Artifacts). SetNumSuites(len(p.Suites)).SetSlack(p.Notifications.Slack). - SetSharding(xcuitest.IsSharded(p.Suites)).SetLaunchOrder(p.Sauce.LaunchOrder). + SetSharding(xcuitest.GetShardTypes(p.Suites), nil).SetLaunchOrder(p.Sauce.LaunchOrder). SetSmartRetry(p.IsSmartRetried()).SetReporters(p.Reporters) tracker.Collect(cases.Title(language.English).String(cmds.FullName(cmd)), props) _ = tracker.Close() diff --git a/internal/cucumber/config.go b/internal/cucumber/config.go index 5a2710522..21dd660b7 100644 --- a/internal/cucumber/config.go +++ b/internal/cucumber/config.go @@ -318,14 +318,30 @@ func FilterSuites(p *Project, suiteName string) error { return fmt.Errorf("no suite named '%s' found", suiteName) } -// IsSharded checks if the suite is sharded -func IsSharded(suites []Suite) bool { +// GetShardTypes returns the shard types in a project. +func GetShardTypes(suites []Suite) []string { + var set = map[string]bool{} for _, s := range suites { if s.Shard != "" { - return true + set[s.Shard] = true } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values +} + +// GetShardOpts returns additional shard options. +func GetShardOpts(suites []Suite) map[string]bool { + var opts = map[string]bool{} + for _, s := range suites { + if s.ShardTagsEnabled { + opts["shard_tags_enabled"] = true + } + } + return opts } // SortByHistory sorts the suites in the order of job history diff --git a/internal/cypress/config.go b/internal/cypress/config.go index 3eccd0157..5f1198a4b 100644 --- a/internal/cypress/config.go +++ b/internal/cypress/config.go @@ -21,7 +21,8 @@ type Project interface { ApplyFlags(selectedSuite string) error AppendTags([]string) Validate() error - IsSharded() bool + GetShardTypes() []string + GetShardOpts() map[string]bool SetDefaults() GetSuiteCount() int diff --git a/internal/cypress/v1/config.go b/internal/cypress/v1/config.go index 80f555f29..7698aacf2 100644 --- a/internal/cypress/v1/config.go +++ b/internal/cypress/v1/config.go @@ -535,14 +535,30 @@ func (p *Project) GetSuite() suite.Suite { } } -// IsSharded returns is it's sharded -func (p *Project) IsSharded() bool { +// GetShardTypes returns the shard types in a project. +func (p *Project) GetShardTypes() []string { + var set = map[string]bool{} for _, s := range p.Suites { if s.Shard != "" { - return true + set[s.Shard] = true } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values +} + +// GetShardOpts returns additional shard options. +func (p *Project) GetShardOpts() map[string]bool { + var opts = map[string]bool{} + for _, s := range p.Suites { + if s.ShardGrepEnabled { + opts["shard_by_grep"] = true + } + } + return opts } // GetAPIVersion returns APIVersion diff --git a/internal/espresso/config.go b/internal/espresso/config.go index 6a01675de..3a1a0ed75 100644 --- a/internal/espresso/config.go +++ b/internal/espresso/config.go @@ -185,6 +185,12 @@ func Validate(p Project) error { return fmt.Errorf(msg.InvalidPassThreshold) } config.ValidateSmartRetry(suite.SmartRetry) + if v, ok := suite.TestOptions["numShards"]; ok { + _, err := strconv.Atoi(fmt.Sprintf("%v", v)) + if err != nil { + return fmt.Errorf("invalid numShards in test option: %v", err) + } + } } if p.Sauce.Retries < 0 { log.Warn().Int("retries", p.Sauce.Retries).Msg(msg.InvalidReries) @@ -232,14 +238,19 @@ func FilterSuites(p *Project, suiteName string) error { return fmt.Errorf(msg.SuiteNameNotFound, suiteName) } -func IsSharded(suites []Suite) bool { +func GetShardTypes(suites []Suite) []string { + var set = map[string]bool{} for _, suite := range suites { if v, ok := suite.TestOptions["numShards"]; ok { - val, err := strconv.Atoi(fmt.Sprintf("%v", v)) - return err == nil && val > 0 + num, _ := strconv.Atoi(fmt.Sprintf("%v", v)) + set["numShards"] = num > 0 } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values } // SortByHistory sorts the suites in the order of job history diff --git a/internal/playwright/config.go b/internal/playwright/config.go index 040dbbdea..9ef810eab 100644 --- a/internal/playwright/config.go +++ b/internal/playwright/config.go @@ -391,13 +391,32 @@ func FilterSuites(p *Project, suiteName string) error { return fmt.Errorf(msg.SuiteNameNotFound, suiteName) } -func IsSharded(suites []Suite) bool { +func GetShardTypes(suites []Suite) []string { + var set = map[string]bool{} for _, s := range suites { - if s.NumShards > 1 || s.Shard != "" { - return true + if s.NumShards > 1 { + set["numShards"] = true + } + if s.Shard != "" { + set[s.Shard] = true } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values +} + +// GetShardOpts returns additional shard options. +func GetShardOpts(suites []Suite) map[string]bool { + var opts = map[string]bool{} + for _, s := range suites { + if s.ShardGrepEnabled { + opts["shard_by_grep"] = true + } + } + return opts } // SortByHistory sorts the suites in the order of job history diff --git a/internal/testcafe/config.go b/internal/testcafe/config.go index 79758d641..fce3337ef 100644 --- a/internal/testcafe/config.go +++ b/internal/testcafe/config.go @@ -387,13 +387,18 @@ func FilterSuites(p *Project, suiteName string) error { return fmt.Errorf("no suite named '%s' found", suiteName) } -func IsSharded(suites []Suite) bool { +func GetShardTypes(suites []Suite) []string { + var set = map[string]bool{} for _, s := range suites { if s.Shard != "" { - return true + set[s.Shard] = true } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values } // SortByHistory sorts the suites in the order of job history diff --git a/internal/usage/tracker.go b/internal/usage/tracker.go index 68ebb332e..f0f0abe70 100644 --- a/internal/usage/tracker.go +++ b/internal/usage/tracker.go @@ -80,8 +80,12 @@ func (p Properties) SetSlack(slack config.Slack) Properties { return p } -func (p Properties) SetSharding(sharded bool) Properties { - p["sharded"] = sharded +func (p Properties) SetSharding(shardTypes []string, shardOpts map[string]bool) Properties { + p["sharded"] = len(shardTypes) > 0 + p["shard_types"] = shardTypes + for k, v := range shardOpts { + p[k] = v + } return p } diff --git a/internal/xcuitest/config.go b/internal/xcuitest/config.go index 277d485de..90647eb89 100644 --- a/internal/xcuitest/config.go +++ b/internal/xcuitest/config.go @@ -357,13 +357,18 @@ func getShardedSuites(suite Suite, ccy int) ([]Suite, error) { return suites, nil } -func IsSharded(suites []Suite) bool { +func GetShardTypes(suites []Suite) []string { + var set = map[string]bool{} for _, s := range suites { if s.Shard != "" { - return true + set[s.Shard] = true } } - return false + var values []string + for k := range set { + values = append(values, k) + } + return values } // IsSmartRetried checks if the suites contain a smartRetried suite